• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 The Chromium OS Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6 
7 #ifdef DRV_MEDIATEK
8 
9 // clang-format off
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <inttypes.h>
13 #include <poll.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <sys/mman.h>
17 #include <unistd.h>
18 #include <xf86drm.h>
19 #include <mediatek_drm.h>
20 // clang-format on
21 
22 #include "drv_helpers.h"
23 #include "drv_priv.h"
24 #include "util.h"
25 
26 #define TILE_TYPE_LINEAR 0
27 
28 // clang-format off
29 #if defined(MTK_MT8183) || \
30     defined(MTK_MT8186)
31 // clang-format on
32 #define SUPPORT_YUV422
33 #endif
34 
35 // All platforms except MT8173 should USE_NV12_FOR_HW_VIDEO_DECODING
36 // and SUPPORT_FP16_AND_10BIT_ABGR
37 // clang-format off
38 #if defined(MTK_MT8183) || \
39     defined(MTK_MT8186) || \
40     defined(MTK_MT8188G) || \
41     defined(MTK_MT8192) || \
42     defined(MTK_MT8195)
43 // clang-format on
44 #define USE_NV12_FOR_HW_VIDEO_DECODING
45 #define SUPPORT_FP16_AND_10BIT_ABGR
46 #else
47 #define DONT_USE_64_ALIGNMENT_FOR_VIDEO_BUFFERS
48 #endif
49 
50 // Devices newer than MT8186 support AR30 overlays and 10-bit video.
51 // clang-format off
52 #if !defined(MTK_MT8173) && \
53     !defined(MTK_MT8183) && \
54     !defined(MTK_MT8186) && \
55     !defined(MTK_MT8192)
56 // clang-format on
57 #define SUPPORT_P010
58 #define SUPPORT_AR30_OVERLAYS
59 #endif
60 
61 // For Mali Sigurd based GPUs, the texture unit reads outside the specified texture dimensions.
62 // Therefore, certain formats require extra memory padding to its allocated surface to prevent the
63 // hardware from reading outside an allocation. For YVU420, we need additional padding for the last
64 // chroma plane.
65 #if defined(MTK_MT8186)
66 #define USE_EXTRA_PADDING_FOR_YVU420
67 #endif
68 
69 struct mediatek_private_map_data {
70 	void *cached_addr;
71 	void *gem_addr;
72 	int prime_fd;
73 };
74 
75 static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888,
76 						  DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888,
77 						  DRM_FORMAT_XRGB8888 };
78 
79 // clang-format off
80 static const uint32_t texture_source_formats[] = {
81 #ifdef SUPPORT_YUV422
82 	DRM_FORMAT_NV21,
83 	DRM_FORMAT_YUYV,
84 #endif
85 #ifdef SUPPORT_P010
86 	DRM_FORMAT_P010,
87 #endif
88 #ifdef SUPPORT_FP16_AND_10BIT_ABGR
89 	DRM_FORMAT_ABGR2101010,
90 	DRM_FORMAT_ABGR16161616F,
91 #endif
92 	DRM_FORMAT_NV12,
93 	DRM_FORMAT_YVU420,
94 	DRM_FORMAT_YVU420_ANDROID
95 };
96 
97 static const uint32_t video_yuv_formats[] = {
98 	DRM_FORMAT_NV21,
99 	DRM_FORMAT_NV12,
100 #ifdef SUPPORT_P010
101 	DRM_FORMAT_P010,
102 #endif
103 	DRM_FORMAT_YUYV,
104 	DRM_FORMAT_YVU420,
105 	DRM_FORMAT_YVU420_ANDROID
106 };
107 // clang-format on
108 
is_video_yuv_format(uint32_t format)109 static bool is_video_yuv_format(uint32_t format)
110 {
111 	size_t i;
112 	for (i = 0; i < ARRAY_SIZE(video_yuv_formats); ++i) {
113 		if (format == video_yuv_formats[i])
114 			return true;
115 	}
116 	return false;
117 }
118 
mediatek_init(struct driver * drv)119 static int mediatek_init(struct driver *drv)
120 {
121 	struct format_metadata metadata;
122 
123 	drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
124 			     &LINEAR_METADATA,
125 			     BO_USE_RENDER_MASK | BO_USE_SCANOUT | BO_USE_PROTECTED);
126 
127 	drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats),
128 			     &LINEAR_METADATA, BO_USE_TEXTURE_MASK | BO_USE_PROTECTED);
129 
130 	drv_add_combination(drv, DRM_FORMAT_R8, &LINEAR_METADATA,
131 			    BO_USE_SW_MASK | BO_USE_LINEAR | BO_USE_PROTECTED);
132 
133 #ifdef SUPPORT_AR30_OVERLAYS
134 	drv_add_combination(drv, DRM_FORMAT_ARGB2101010, &LINEAR_METADATA,
135 			    BO_USE_TEXTURE | BO_USE_SCANOUT | BO_USE_PROTECTED | BO_USE_LINEAR);
136 #endif
137 
138 	/* YUYV format for video overlay and camera subsystem. */
139 	drv_add_combination(drv, DRM_FORMAT_YUYV, &LINEAR_METADATA,
140 			    BO_USE_HW_VIDEO_DECODER | BO_USE_SCANOUT | BO_USE_LINEAR |
141 				BO_USE_TEXTURE | BO_USE_PROTECTED);
142 
143 	/* Android CTS tests require this. */
144 	drv_add_combination(drv, DRM_FORMAT_BGR888, &LINEAR_METADATA, BO_USE_SW_MASK);
145 
146 	/* Support BO_USE_HW_VIDEO_DECODER for protected content minigbm allocations. */
147 	metadata.tiling = TILE_TYPE_LINEAR;
148 	metadata.priority = 1;
149 	metadata.modifier = DRM_FORMAT_MOD_LINEAR;
150 	drv_modify_combination(drv, DRM_FORMAT_YVU420, &metadata,
151 			       BO_USE_HW_VIDEO_DECODER | BO_USE_PROTECTED);
152 #ifdef MTK_MT8173
153 	/*
154 	 * b/292507490: The MT8173 decoder can output YUV420 only. Some CTS tests feed the
155 	 * decoded buffer to the hardware encoder and the tests allocate the buffer with
156 	 * DRM_FORMAT_FLEX_YCbCr_420_888 with the mask of BO_USE_HW_VIDEO_ENCODER |
157 	 * BO_USE_HW_VIDEO_DECODER. Therefore, we have to allocate YUV420 in the case.
158 	 */
159 	drv_modify_combination(drv, DRM_FORMAT_YVU420, &metadata, BO_USE_HW_VIDEO_ENCODER);
160 #endif
161 	drv_modify_combination(drv, DRM_FORMAT_YVU420_ANDROID, &metadata,
162 			       BO_USE_HW_VIDEO_DECODER | BO_USE_PROTECTED);
163 #ifdef USE_NV12_FOR_HW_VIDEO_DECODING
164 	// TODO(hiroh): Switch to use NV12 for video decoder on MT8173 as well.
165 	drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata,
166 			       BO_USE_HW_VIDEO_DECODER | BO_USE_PROTECTED);
167 #endif
168 	drv_modify_combination(drv, DRM_FORMAT_P010, &metadata,
169 			       BO_USE_HW_VIDEO_DECODER | BO_USE_PROTECTED);
170 
171 	/*
172 	 * R8 format is used for Android's HAL_PIXEL_FORMAT_BLOB for input/output from
173 	 * hardware decoder/encoder.
174 	 */
175 	drv_modify_combination(drv, DRM_FORMAT_R8, &metadata,
176 			       BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER |
177 				   BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE |
178 				   BO_USE_GPU_DATA_BUFFER | BO_USE_SENSOR_DIRECT_DATA);
179 
180 	/* NV12 format for encoding and display. */
181 	drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata,
182 			       BO_USE_SCANOUT | BO_USE_HW_VIDEO_ENCODER | BO_USE_CAMERA_READ |
183 				   BO_USE_CAMERA_WRITE);
184 
185 #ifdef MTK_MT8183
186 	/* Only for MT8183 Camera subsystem */
187 	drv_modify_combination(drv, DRM_FORMAT_NV21, &metadata,
188 			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
189 	drv_modify_combination(drv, DRM_FORMAT_YUYV, &metadata,
190 			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
191 	drv_modify_combination(drv, DRM_FORMAT_YVU420, &metadata,
192 			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
193 	/* Private formats for private reprocessing in camera */
194 	drv_add_combination(drv, DRM_FORMAT_MTISP_SXYZW10, &metadata,
195 			    BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_SW_MASK);
196 #endif
197 
198 	return drv_modify_linear_combinations(drv);
199 }
200 
mediatek_bo_create_with_modifiers(struct bo * bo,uint32_t width,uint32_t height,uint32_t format,const uint64_t * modifiers,uint32_t count)201 static int mediatek_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint32_t height,
202 					     uint32_t format, const uint64_t *modifiers,
203 					     uint32_t count)
204 {
205 	int ret;
206 	size_t plane;
207 	uint32_t stride;
208 	struct drm_mtk_gem_create gem_create = { 0 };
209 	/*
210 	 * We identify the ChromeOS Camera App buffers via these two USE flags. Those buffers need
211 	 * the same alignment as the video hardware encoding.
212 	 */
213 	const bool is_camera_preview =
214 	    (bo->meta.use_flags & BO_USE_SCANOUT) && (bo->meta.use_flags & BO_USE_CAMERA_WRITE);
215 	const bool is_hw_video_encoder = bo->meta.use_flags & BO_USE_HW_VIDEO_ENCODER;
216 #ifdef MTK_MT8173
217 	const bool is_mt8173_video_decoder = bo->meta.use_flags & BO_USE_HW_VIDEO_DECODER;
218 #else
219 	const bool is_mt8173_video_decoder = false;
220 #endif
221 	/*
222 	 * Android sends blobs for encoding in the shape of a single-row pixel buffer. Use R8 +
223 	 * single row as a proxy for Android HAL_PIXEL_FORMAT_BLOB until a drm equivalent is
224 	 * defined.
225 	 */
226 	const bool is_format_blob = format == DRM_FORMAT_R8 && height == 1;
227 
228 	if (!drv_has_modifier(modifiers, count, DRM_FORMAT_MOD_LINEAR)) {
229 		errno = EINVAL;
230 		drv_loge("no usable modifier found\n");
231 		return -EINVAL;
232 	}
233 
234 	/*
235 	 * Since the ARM L1 cache line size is 64 bytes, align to that as a
236 	 * performance optimization, except for video buffers on certain platforms,
237 	 * these should only be accessed from the GPU and VCODEC subsystems (maybe
238 	 * also MDP), so it's better to align to macroblocks.
239 	 */
240 	stride = drv_stride_from_format(format, width, 0);
241 #ifdef DONT_USE_64_ALIGNMENT_FOR_VIDEO_BUFFERS
242 	const uint32_t alignment = is_video_yuv_format(format) ? 16 : 64;
243 	stride = ALIGN(stride, alignment);
244 #else
245 	stride = ALIGN(stride, 64);
246 #endif
247 
248 	/*
249 	 * The mediatek video decoder requires to align width and height by 64. But this is
250 	 * the requirement for mediatek tiled format (e.g. MT21 and MM21). The buffers are
251 	 * not allocated by minigbm. So we don't have to care about it. The tiled buffer is
252 	 * converted to NV12 or YV12, which is allocated by minigbm. V4L2 MDP doesn't
253 	 * require any special alignment for them.
254 	 * On the other hand, the mediatek video encoder reuqires a padding on each plane.
255 	 * When both video decoder and encoder use flag is masked (in some CTS test), we
256 	 * align with the encoder alignment.
257 	 * However, V4L2VideoDecodeAccelerator used on MT8173 fails handling the buffer with
258 	 * padding, although V4L2VideoDecoder used on MT8183 and later can do. We workaround
259 	 * this problem to allocate a buffer without padding on MT8173. This works because
260 	 * MT8173 decoder's output NV12 is converted to YV12 buffer that is allocated with
261 	 * video encoder usage mask only and thus have padding in Android.
262 	 * See go/mediatek-video-buffer-alignment-note for detail.
263 	 */
264 	if ((is_hw_video_encoder && !is_mt8173_video_decoder && !is_format_blob) ||
265 	    is_camera_preview) {
266 		uint32_t aligned_height = ALIGN(height, 32);
267 		uint32_t padding[DRV_MAX_PLANES] = { 0 };
268 
269 		for (plane = 0; plane < bo->meta.num_planes; ++plane) {
270 			uint32_t plane_stride = drv_stride_from_format(format, stride, plane);
271 			padding[plane] = plane_stride *
272 					 (32 / drv_vertical_subsampling_from_format(format, plane));
273 		}
274 
275 		drv_bo_from_format_and_padding(bo, stride, 1, aligned_height, format, padding);
276 	} else {
277 #ifdef USE_EXTRA_PADDING_FOR_YVU420
278 		/*
279 		 * Apply extra padding for YV12 if the height does not meet round up requirement and
280 		 * the image is to be sampled by gpu.
281 		 */
282 		static const uint32_t required_round_up = 4;
283 		const uint32_t height_mod = height % required_round_up;
284 		const bool is_texture = bo->meta.use_flags & BO_USE_TEXTURE;
285 		/*
286 		 * YVU420 and YVU420_ANDROID treatments have been aligned in mediatek backend. Check
287 		 * both since gbm frontend still maps linear YVU420 to YVU420_ANDROID for other hw
288 		 * backends.
289 		 */
290 		const bool is_format_yv12 =
291 		    format == DRM_FORMAT_YVU420 || format == DRM_FORMAT_YVU420_ANDROID;
292 #endif
293 #ifdef SUPPORT_YUV422
294 		/*
295 		 * JPEG Encoder Accelerator requires 16x16 alignment. We want the buffer
296 		 * from camera can be put in JEA directly so align the height to 16
297 		 * bytes.
298 		 */
299 		if (format == DRM_FORMAT_NV12)
300 			height = ALIGN(height, 16);
301 #endif
302 		drv_bo_from_format(bo, stride, 1, height, format);
303 
304 #ifdef USE_EXTRA_PADDING_FOR_YVU420
305 		if (is_format_yv12 && is_texture && height_mod) {
306 			const uint32_t height_padding = required_round_up - height_mod;
307 			const uint32_t y_padding =
308 			    drv_size_from_format(format, bo->meta.strides[0], height_padding, 0);
309 			const uint32_t u_padding =
310 			    drv_size_from_format(format, bo->meta.strides[2], height_padding, 2);
311 			const uint32_t vu_size = drv_bo_get_plane_size(bo, 2) * 2;
312 
313 			bo->meta.total_size += u_padding;
314 
315 			/*
316 			 * Since we are not aligning Y, we must make sure that its padding fits
317 			 * inside the rest of the space allocated for the V/U planes.
318 			 */
319 			if (y_padding > vu_size) {
320 				/* Align with mali workaround to pad all 3 planes. */
321 				bo->meta.total_size += y_padding + u_padding;
322 			}
323 		}
324 #endif
325 	}
326 
327 	gem_create.size = bo->meta.total_size;
328 
329 	/* For protected data buffer needs to be allocated from GEM */
330 	if (bo->meta.use_flags & BO_USE_PROTECTED)
331 		gem_create.flags |= DRM_MTK_GEM_CREATE_ENCRYPTED;
332 
333 	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MTK_GEM_CREATE, &gem_create);
334 	if (ret) {
335 		drv_loge("DRM_IOCTL_MTK_GEM_CREATE failed (size=%" PRIu64 ")\n", gem_create.size);
336 		return -errno;
337 	}
338 
339 	bo->handle.u32 = gem_create.handle;
340 
341 	return 0;
342 }
343 
mediatek_bo_create(struct bo * bo,uint32_t width,uint32_t height,uint32_t format,uint64_t use_flags)344 static int mediatek_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
345 			      uint64_t use_flags)
346 {
347 	uint64_t modifiers[] = { DRM_FORMAT_MOD_LINEAR };
348 	return mediatek_bo_create_with_modifiers(bo, width, height, format, modifiers,
349 						 ARRAY_SIZE(modifiers));
350 }
351 
mediatek_bo_map(struct bo * bo,struct vma * vma,uint32_t map_flags)352 static void *mediatek_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags)
353 {
354 	int ret, prime_fd;
355 	struct drm_mtk_gem_map_off gem_map = { 0 };
356 	struct mediatek_private_map_data *priv;
357 	void *addr = NULL;
358 
359 	gem_map.handle = bo->handle.u32;
360 
361 	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MTK_GEM_MAP_OFFSET, &gem_map);
362 	if (ret) {
363 		drv_loge("DRM_IOCTL_MTK_GEM_MAP_OFFSET failed\n");
364 		return MAP_FAILED;
365 	}
366 
367 	prime_fd = drv_bo_get_plane_fd(bo, 0);
368 	if (prime_fd < 0) {
369 		drv_loge("Failed to get a prime fd\n");
370 		return MAP_FAILED;
371 	}
372 
373 	addr = mmap(0, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd,
374 		    gem_map.offset);
375 	if (addr == MAP_FAILED)
376 		goto out_close_prime_fd;
377 
378 	vma->length = bo->meta.total_size;
379 
380 	priv = calloc(1, sizeof(*priv));
381 	if (!priv)
382 		goto out_unmap_addr;
383 
384 	if (bo->meta.use_flags & BO_USE_RENDERSCRIPT) {
385 		priv->cached_addr = calloc(1, bo->meta.total_size);
386 		if (!priv->cached_addr)
387 			goto out_free_priv;
388 
389 		priv->gem_addr = addr;
390 		addr = priv->cached_addr;
391 	}
392 
393 	priv->prime_fd = prime_fd;
394 	vma->priv = priv;
395 
396 	return addr;
397 
398 out_free_priv:
399 	free(priv);
400 out_unmap_addr:
401 	munmap(addr, bo->meta.total_size);
402 out_close_prime_fd:
403 	close(prime_fd);
404 	return MAP_FAILED;
405 }
406 
mediatek_bo_unmap(struct bo * bo,struct vma * vma)407 static int mediatek_bo_unmap(struct bo *bo, struct vma *vma)
408 {
409 	if (vma->priv) {
410 		struct mediatek_private_map_data *priv = vma->priv;
411 
412 		if (priv->cached_addr) {
413 			vma->addr = priv->gem_addr;
414 			free(priv->cached_addr);
415 		}
416 
417 		close(priv->prime_fd);
418 		free(priv);
419 		vma->priv = NULL;
420 	}
421 
422 	return munmap(vma->addr, vma->length);
423 }
424 
mediatek_bo_invalidate(struct bo * bo,struct mapping * mapping)425 static int mediatek_bo_invalidate(struct bo *bo, struct mapping *mapping)
426 {
427 	struct mediatek_private_map_data *priv = mapping->vma->priv;
428 
429 	if (priv) {
430 		struct pollfd fds = {
431 			.fd = priv->prime_fd,
432 		};
433 
434 		if (mapping->vma->map_flags & BO_MAP_WRITE)
435 			fds.events |= POLLOUT;
436 
437 		if (mapping->vma->map_flags & BO_MAP_READ)
438 			fds.events |= POLLIN;
439 
440 		poll(&fds, 1, -1);
441 		if (fds.revents != fds.events)
442 			drv_loge("poll prime_fd failed\n");
443 
444 		if (priv->cached_addr)
445 			memcpy(priv->cached_addr, priv->gem_addr, bo->meta.total_size);
446 	}
447 
448 	return 0;
449 }
450 
mediatek_bo_flush(struct bo * bo,struct mapping * mapping)451 static int mediatek_bo_flush(struct bo *bo, struct mapping *mapping)
452 {
453 	struct mediatek_private_map_data *priv = mapping->vma->priv;
454 	if (priv && priv->cached_addr && (mapping->vma->map_flags & BO_MAP_WRITE))
455 		memcpy(priv->gem_addr, priv->cached_addr, bo->meta.total_size);
456 
457 	return 0;
458 }
459 
mediatek_resolve_format_and_use_flags(struct driver * drv,uint32_t format,uint64_t use_flags,uint32_t * out_format,uint64_t * out_use_flags)460 static void mediatek_resolve_format_and_use_flags(struct driver *drv, uint32_t format,
461 						  uint64_t use_flags, uint32_t *out_format,
462 						  uint64_t *out_use_flags)
463 {
464 	*out_format = format;
465 	*out_use_flags = use_flags;
466 	switch (format) {
467 	case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
468 #ifdef MTK_MT8183
469 		/* Only MT8183 Camera subsystem offers private reprocessing
470 		 * capability. CAMERA_READ indicates the buffer is intended for
471 		 * reprocessing and hence given the private format for MTK. */
472 		if (use_flags & BO_USE_CAMERA_READ) {
473 			*out_format = DRM_FORMAT_MTISP_SXYZW10;
474 			break;
475 		}
476 #endif
477 		if (use_flags & BO_USE_CAMERA_WRITE) {
478 			*out_format = DRM_FORMAT_NV12;
479 			break;
480 		}
481 
482 		/* HACK: See b/28671744 */
483 		*out_format = DRM_FORMAT_XBGR8888;
484 		*out_use_flags &= ~BO_USE_HW_VIDEO_ENCODER;
485 		break;
486 	case DRM_FORMAT_FLEX_YCbCr_420_888:
487 #ifdef USE_NV12_FOR_HW_VIDEO_DECODING
488 		// TODO(hiroh): Switch to use NV12 for video decoder on MT8173 as well.
489 		if (use_flags & (BO_USE_HW_VIDEO_DECODER)) {
490 			*out_format = DRM_FORMAT_NV12;
491 			break;
492 		}
493 #endif
494 		/*
495 		 * b/292507490: The MT8173 decoder can output YUV420 only. Some CTS tests feed the
496 		 * decoded buffer to the hardware encoder and the tests allocate the buffer with
497 		 * DRM_FORMAT_FLEX_YCbCr_420_888 with the mask of BO_USE_HW_VIDEO_ENCODER |
498 		 * BO_USE_HW_VIDEO_DECODER. Therefore, we have to allocate YUV420 in the case.
499 		 */
500 		if (use_flags &
501 		    (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_ENCODER)) {
502 #ifndef MTK_MT8173
503 			*out_format = DRM_FORMAT_NV12;
504 			break;
505 #else
506 			if (!(use_flags & BO_USE_HW_VIDEO_DECODER)) {
507 				*out_format = DRM_FORMAT_NV12;
508 				break;
509 			}
510 #endif
511 		}
512 		/* HACK: See b/139714614 */
513 		*out_format = DRM_FORMAT_YVU420;
514 		*out_use_flags &= ~BO_USE_SCANOUT;
515 		break;
516 	default:
517 		break;
518 	}
519 	/* Mediatek doesn't support YUV overlays */
520 	if (is_video_yuv_format(format))
521 		*out_use_flags &= ~BO_USE_SCANOUT;
522 }
523 
524 const struct backend backend_mediatek = {
525 	.name = "mediatek",
526 	.init = mediatek_init,
527 	.bo_create = mediatek_bo_create,
528 	.bo_create_with_modifiers = mediatek_bo_create_with_modifiers,
529 	.bo_destroy = drv_gem_bo_destroy,
530 	.bo_import = drv_prime_bo_import,
531 	.bo_map = mediatek_bo_map,
532 	.bo_unmap = mediatek_bo_unmap,
533 	.bo_invalidate = mediatek_bo_invalidate,
534 	.bo_flush = mediatek_bo_flush,
535 	.resolve_format_and_use_flags = mediatek_resolve_format_and_use_flags,
536 };
537 
538 #endif
539