1111#include <drm/drm_fourcc.h>
1212#include <drm/drm_framebuffer.h>
1313#include <drm/drm_gem_atomic_helper.h>
14+ #include <linux/align.h>
1415
1516#include "mtk_drm_crtc.h"
1617#include "mtk_drm_ddp_comp.h"
@@ -32,6 +33,14 @@ static const u32 formats[] = {
3233 DRM_FORMAT_YUYV ,
3334};
3435
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+
3544static void mtk_plane_reset (struct drm_plane * plane )
3645{
3746 struct mtk_plane_state * state ;
@@ -51,6 +60,7 @@ static void mtk_plane_reset(struct drm_plane *plane)
5160
5261 state -> base .plane = plane ;
5362 state -> pending .format = DRM_FORMAT_RGB565 ;
63+ state -> pending .modifier = DRM_FORMAT_MOD_LINEAR ;
5464}
5565
5666static 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
7181 return & state -> base ;
7282}
7383
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+
74110static void mtk_drm_plane_destroy_state (struct drm_plane * plane ,
75111 struct drm_plane_state * state )
76112{
@@ -119,21 +155,52 @@ static void mtk_plane_update_new_state(struct drm_plane_state *new_state,
119155 struct drm_gem_object * gem ;
120156 struct mtk_drm_gem_obj * mtk_gem ;
121157 unsigned int pitch , format ;
158+ u64 modifier ;
122159 dma_addr_t addr ;
160+ dma_addr_t hdr_addr = 0 ;
161+ unsigned int hdr_pitch = 0 ;
123162
124163 gem = fb -> obj [0 ];
125164 mtk_gem = to_mtk_gem_obj (gem );
126165 addr = mtk_gem -> dma_addr ;
127166 pitch = fb -> pitches [0 ];
128167 format = fb -> format -> format ;
168+ modifier = fb -> modifier ;
129169
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+ }
132196
133197 mtk_plane_state -> pending .enable = true;
134198 mtk_plane_state -> pending .pitch = pitch ;
199+ mtk_plane_state -> pending .hdr_pitch = hdr_pitch ;
135200 mtk_plane_state -> pending .format = format ;
201+ mtk_plane_state -> pending .modifier = modifier ;
136202 mtk_plane_state -> pending .addr = addr ;
203+ mtk_plane_state -> pending .hdr_addr = hdr_addr ;
137204 mtk_plane_state -> pending .x = new_state -> dst .x1 ;
138205 mtk_plane_state -> pending .y = new_state -> dst .y1 ;
139206 mtk_plane_state -> pending .width = drm_rect_width (& new_state -> dst );
@@ -172,6 +239,7 @@ static const struct drm_plane_funcs mtk_plane_funcs = {
172239 .reset = mtk_plane_reset ,
173240 .atomic_duplicate_state = mtk_plane_duplicate_state ,
174241 .atomic_destroy_state = mtk_drm_plane_destroy_state ,
242+ .format_mod_supported = mtk_plane_format_mod_supported ,
175243};
176244
177245static 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,
253321
254322 err = drm_universal_plane_init (dev , plane , possible_crtcs ,
255323 & mtk_plane_funcs , formats ,
256- ARRAY_SIZE (formats ), NULL , type , NULL );
324+ ARRAY_SIZE (formats ), modifiers , type , NULL );
257325 if (err ) {
258326 DRM_ERROR ("failed to initialize plane\n" );
259327 return err ;
0 commit comments