1/* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "display_gralloc.h" 17#include <errno.h> 18#include <inttypes.h> 19#include <stdio.h> 20#include <sys/mman.h> 21#include <sys/shm.h> 22#include <securec.h> 23#include "buffer_handle.h" 24#include "display_type.h" 25#include "disp_common.h" 26#include "hdf_log.h" 27 28#define DEFAULT_READ_WRITE_PERMISSIONS 0666 29#define MAX_MALLOC_SIZE 0x10000000L 30#define SHM_MAX_KEY 10000 31#define SHM_START_KEY 1 32#define INVALID_SHMID -1 33#define BITS_PER_BYTE 8 34 35#define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d)) 36#define ALIGN_UP(x, a) ((((x) + ((a)-1)) / (a)) * (a)) 37#define HEIGHT_ALIGN 2U 38#define WIDTH_ALIGN 8U 39#define MAX_PLANES 3 40 41typedef struct { 42 BufferHandle hdl; 43 int32_t shmid; 44} PriBufferHandle; 45 46typedef struct { 47 uint32_t numPlanes; 48 uint32_t radio[MAX_PLANES]; 49} PlaneLayoutInfo; 50 51typedef struct { 52 uint32_t format; 53 uint32_t bitsPerPixel; // bits per pixel for first plane 54 const PlaneLayoutInfo *planes; 55} FormatInfo; 56 57static const PlaneLayoutInfo g_yuv420SPLayout = { 58 .numPlanes = 2, 59 .radio = { 4, 2 }, 60}; 61 62static const PlaneLayoutInfo g_yuv420PLayout = { 63 .numPlanes = 3, 64 .radio = { 4, 1, 1 }, 65}; 66 67static const FormatInfo *GetFormatInfo(uint32_t format) 68{ 69 static const FormatInfo fmtInfos[] = { 70 {PIXEL_FMT_RGBX_8888, 32, NULL}, {PIXEL_FMT_RGBA_8888, 32, NULL}, 71 {PIXEL_FMT_BGRX_8888, 32, NULL}, {PIXEL_FMT_BGRA_8888, 32, NULL}, 72 {PIXEL_FMT_RGB_888, 24, NULL}, {PIXEL_FMT_BGR_565, 16, NULL}, 73 {PIXEL_FMT_RGBA_5551, 16, NULL}, {PIXEL_FMT_RGB_565, 16, NULL}, 74 {PIXEL_FMT_BGRX_4444, 16, NULL}, {PIXEL_FMT_BGRA_4444, 16, NULL}, 75 {PIXEL_FMT_RGBA_4444, 16, NULL}, {PIXEL_FMT_RGBX_4444, 16, NULL}, 76 {PIXEL_FMT_BGRX_5551, 16, NULL}, {PIXEL_FMT_BGRA_5551, 16, NULL}, 77 {PIXEL_FMT_YCBCR_420_SP, 8, &g_yuv420SPLayout}, {PIXEL_FMT_YCRCB_420_SP, 8, &g_yuv420SPLayout}, 78 {PIXEL_FMT_YCBCR_420_P, 8, &g_yuv420PLayout}, {PIXEL_FMT_YCRCB_420_P, 8, &g_yuv420PLayout}, 79 }; 80 81 for (uint32_t i = 0; i < sizeof(fmtInfos) / sizeof(FormatInfo); i++) { 82 if (fmtInfos[i].format == format) { 83 return &fmtInfos[i]; 84 } 85 } 86 HDF_LOGE("the format can not support %d %d", format, PIXEL_FMT_RGBA_8888); 87 return NULL; 88} 89 90static uint32_t AdjustStrideFromFormat(uint32_t format, uint32_t width) 91{ 92 const FormatInfo *fmtInfo = GetFormatInfo(format); 93 if ((fmtInfo != NULL) && (fmtInfo->planes != NULL)) { 94 uint32_t sum = fmtInfo->planes->radio[0]; 95 for (uint32_t i = 1; (i < fmtInfo->planes->numPlanes) && (i < MAX_PLANES); i++) { 96 sum += fmtInfo->planes->radio[i]; 97 } 98 if (sum > 0) { 99 width = DIV_ROUND_UP((width * sum), fmtInfo->planes->radio[0]); 100 } 101 } 102 return width; 103} 104 105static int32_t InitBufferHandle(PriBufferHandle* buffer, const AllocInfo* info) 106{ 107 int32_t size; 108 int32_t stride; 109 int32_t h = ALIGN_UP(info->height, HEIGHT_ALIGN); 110 const FormatInfo *fmtInfo = GetFormatInfo(info->format); 111 if (fmtInfo == NULL) { 112 HDF_LOGE("can not get format information : %d", buffer->hdl.format); 113 return DISPLAY_FAILURE; 114 } 115 116 stride = ALIGN_UP(AdjustStrideFromFormat(info->format, info->width), WIDTH_ALIGN) * 117 fmtInfo->bitsPerPixel / BITS_PER_BYTE; 118 size = h * stride; 119 buffer->hdl.width = info->width; 120 buffer->hdl.stride = stride; 121 buffer->hdl.height = info->height; 122 buffer->hdl.size = size; 123 buffer->hdl.usage = info->usage; 124 buffer->hdl.fd = -1; 125 buffer->shmid = INVALID_SHMID; 126 buffer->hdl.format = info->format; 127 buffer->hdl.reserveInts = (sizeof(PriBufferHandle) - sizeof(BufferHandle) - 128 buffer->hdl.reserveFds * sizeof(uint32_t)) / sizeof(uint32_t); 129 return DISPLAY_SUCCESS; 130} 131 132static int32_t AllocShm(BufferHandle *buffer) 133{ 134 static int32_t key = SHM_START_KEY; 135 int32_t shmid; 136 137 while ((shmid = shmget(key, buffer->size, IPC_CREAT | IPC_EXCL | DEFAULT_READ_WRITE_PERMISSIONS)) < 0) { 138 if (errno != EEXIST) { 139 HDF_LOGE("%s: fail to alloc the shared memory, errno = %d", __func__, errno); 140 return DISPLAY_FAILURE; 141 } 142 key++; 143 if (key >= SHM_MAX_KEY) { 144 key = SHM_START_KEY; 145 } 146 } 147 void *pBase = shmat(shmid, NULL, 0); 148 if (pBase == ((void *)-1)) { 149 HDF_LOGE("%s: Fail to attach the shared memory, errno = %d", __func__, errno); 150 if (shmctl(shmid, IPC_RMID, 0) == -1) { 151 HDF_LOGE("%s: Fail to free shmid, errno = %d", __func__, errno); 152 } 153 return DISPLAY_FAILURE; 154 } 155 buffer->virAddr = pBase; 156 buffer->fd = key; 157 ((PriBufferHandle*)buffer)->shmid = shmid; 158 key++; 159 (void)memset_s(pBase, buffer->size, 0x0, buffer->size); 160 if (key >= SHM_MAX_KEY) { 161 key = SHM_START_KEY; 162 } 163 return DISPLAY_SUCCESS; 164} 165 166typedef enum { 167 MMZ_CACHE = 1, /* allocate mmz with cache attribute */ 168 MMZ_NOCACHE, /* allocate mmz with nocache attribute */ 169 MMZ_FREE, /* free mmz */ 170 MAP_CACHE, 171 MAP_NOCACHE, 172 UNMAP, 173 FLUSH_CACHE, 174 FLUSH_NOCACHE, 175 INVALIDATE, 176 MMZ_MAX 177} MMZ_TYPE; 178 179typedef struct { 180 void *vaddr; 181 uint64_t paddr; 182 int32_t size; 183} MmzMemory; 184 185#define MMZ_IOC_MAGIC 'M' 186#define MMZ_CACHE_TYPE _IOR(MMZ_IOC_MAGIC, MMZ_CACHE, MmzMemory) 187#define MMZ_NOCACHE_TYPE _IOR(MMZ_IOC_MAGIC, MMZ_NOCACHE, MmzMemory) 188#define MMZ_FREE_TYPE _IOR(MMZ_IOC_MAGIC, MMZ_FREE, MmzMemory) 189#define MMZ_MAP_CACHE_TYPE _IOR(MMZ_IOC_MAGIC, MAP_CACHE, MmzMemory) 190#define MMZ_MAP_NOCACHE_TYPE _IOR(MMZ_IOC_MAGIC, MAP_NOCACHE, MmzMemory) 191#define MMZ_UNMAP_TYPE _IOR(MMZ_IOC_MAGIC, UNMAP, MmzMemory) 192#define MMZ_FLUSH_CACHE_TYPE _IOR(MMZ_IOC_MAGIC, FLUSH_CACHE, MmzMemory) 193#define MMZ_FLUSH_NOCACHE_TYPE _IOR(MMZ_IOC_MAGIC, FLUSH_NOCACHE, MmzMemory) 194#define MMZ_INVALIDATE_TYPE _IOR(MMZ_IOC_MAGIC, INVALIDATE, MmzMemory) 195 196#define MMZ_NODE "/dev/mmz" 197 198static int SendCmd(int cmd, unsigned long arg) 199{ 200 int fd = open(MMZ_NODE, O_RDONLY); 201 if (fd != -1) { 202 int ret = ioctl(fd, cmd, arg); 203 if (ret == -1) { 204 printf("[Init] 1 [ERR] %d!\n", errno); 205 } 206 close(fd); 207 return ret; 208 } 209 return fd; 210} 211 212static int32_t AllocMmz(BufferHandle *buffer) 213{ 214 int32_t ret; 215 216 MmzMemory mmz = {0}; 217 mmz.size = buffer->size; 218 switch (buffer->usage) { 219 case HBM_USE_MEM_MMZ_CACHE: 220 printf("req size(%#x), ret:%d \n", buffer->size, SendCmd(MMZ_CACHE_TYPE, (uintptr_t)&mmz)); 221 printf("vaddr %#x, paddr: %#x\n", mmz.vaddr, mmz.paddr); 222 ret = 0; 223 break; 224 case HBM_USE_MEM_MMZ: 225 printf("req size(%#x), ret:%d \n", buffer->size, SendCmd(MMZ_NOCACHE_TYPE, (uintptr_t)&mmz)); 226 printf("vaddr %#x, paddr: %#x\n", mmz.vaddr, mmz.paddr); 227 ret = 0; 228 break; 229 default: 230 HDF_LOGE("%s: not support memory usage: 0x%" PRIx64 "", __func__, buffer->usage); 231 return DISPLAY_NOT_SUPPORT; 232 } 233 if (ret != DISPLAY_SUCCESS) { 234 HDF_LOGE("%s: mmzalloc failure, usage = 0x%" PRIx64 ", ret 0x%x", __func__, 235 buffer->usage, ret); 236 return DISPLAY_FAILURE; 237 } 238 (void)memset_s(mmz.vaddr, buffer->size, 0x0, buffer->size); 239 buffer->phyAddr = mmz.paddr; 240 buffer->virAddr = mmz.vaddr; 241 return DISPLAY_SUCCESS; 242} 243 244static int32_t FreeMmz(uint64_t paddr, void* vaddr) 245{ 246 MmzMemory mmz = {0}; 247 mmz.vaddr = vaddr; 248 mmz.paddr = paddr; 249 return SendCmd(MMZ_FREE_TYPE, (uintptr_t)&mmz); 250} 251 252static int32_t MmzFlushCache(BufferHandle *buffer) 253{ 254 MmzMemory mmz = {0}; 255 mmz.paddr = buffer->phyAddr; 256 mmz.size = buffer->size; 257 mmz.vaddr = buffer->virAddr; 258 return SendCmd(MMZ_FLUSH_CACHE_TYPE, (uintptr_t)&mmz); 259} 260 261static int32_t MmzInvalidateCache(BufferHandle *buffer) 262{ 263 MmzMemory mmz = {0}; 264 mmz.paddr = buffer->phyAddr; 265 mmz.size = buffer->size; 266 mmz.vaddr = buffer->virAddr; 267 return SendCmd(MMZ_INVALIDATE_TYPE, (uintptr_t)&mmz); 268} 269 270static int32_t AllocMem(const AllocInfo* info, BufferHandle **buffer) 271{ 272 int32_t ret; 273 DISPLAY_CHK_RETURN((buffer == NULL), DISPLAY_NULL_PTR, HDF_LOGE("%s: in buffer is null", __func__)); 274 DISPLAY_CHK_RETURN((info == NULL), DISPLAY_NULL_PTR, HDF_LOGE("%s: in info is null", __func__)); 275 PriBufferHandle* priBuffer = calloc(1, sizeof(PriBufferHandle)); 276 DISPLAY_CHK_RETURN((priBuffer == NULL), DISPLAY_NULL_PTR, HDF_LOGE("%s: can not calloc errno : %d", 277 __func__, errno)); 278 ret = InitBufferHandle(priBuffer, info); 279 DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, HDF_LOGE("%s: can not init buffe handle", 280 __func__); goto OUT); 281 282 BufferHandle *bufferHdl = &priBuffer->hdl; 283 DISPLAY_CHK_RETURN(((bufferHdl->size > MAX_MALLOC_SIZE) || (bufferHdl->size == 0)), 284 DISPLAY_FAILURE, HDF_LOGE("%s: size is invalid %d ", __func__, bufferHdl->size); goto OUT); 285 286 if (bufferHdl->usage == HBM_USE_MEM_SHARE) { 287 ret = AllocShm(bufferHdl); 288 } else if ((bufferHdl->usage == HBM_USE_MEM_DMA ) || (bufferHdl->usage == HBM_USE_MEM_MMZ )) { 289 ret = AllocMmz(bufferHdl); 290 } else { 291 HDF_LOGE("%s: not support memory usage: 0x%" PRIx64 "", __func__, bufferHdl->usage); 292 ret = DISPLAY_NOT_SUPPORT; 293 } 294 295OUT: 296 if ((ret != DISPLAY_SUCCESS) && (bufferHdl != NULL)) { 297 free(bufferHdl); 298 bufferHdl = NULL; 299 } 300 *buffer = bufferHdl; 301 return ret; 302} 303 304static void FreeShm(BufferHandle *buffer) 305{ 306 CHECK_NULLPOINTER_RETURN(buffer->virAddr); 307 if (shmdt(buffer->virAddr) == -1) { 308 HDF_LOGE("%s: Fail to free shared memory, errno = %d", __func__, errno); 309 } 310 if (shmctl(((PriBufferHandle*)buffer)->shmid, IPC_RMID, 0) == -1) { 311 HDF_LOGE("%s: Fail to free shmid, errno = %d", __func__, errno); 312 } 313} 314 315static void FreeMem(BufferHandle *buffer) 316{ 317 int ret; 318 319 CHECK_NULLPOINTER_RETURN(buffer); 320 if ((buffer->size > MAX_MALLOC_SIZE) || (buffer->size == 0)) { 321 HDF_LOGE("%s: size is invalid, buffer->size = %d", __func__, buffer->size); 322 return; 323 } 324 325 switch (buffer->usage) { 326 case HBM_USE_MEM_MMZ_CACHE: 327 case HBM_USE_MEM_MMZ: 328 ret = FreeMmz(buffer->phyAddr, buffer->virAddr); 329 if (ret != DISPLAY_SUCCESS) { 330 HDF_LOGE("%s: HI_MPI_SYS_MmzFree failure, ret 0x%x", __func__, ret); 331 } 332 break; 333 case HBM_USE_MEM_SHARE: 334 FreeShm(buffer); 335 break; 336 default: 337 HDF_LOGE("%s: not support memory usage: 0x%" PRIx64 "", __func__, buffer->usage); 338 } 339} 340 341static void *MmapShm(BufferHandle *buffer) 342{ 343 int32_t shmid; 344 345 shmid = shmget(buffer->fd, buffer->size, IPC_EXCL | DEFAULT_READ_WRITE_PERMISSIONS); 346 if (shmid < 0) { 347 HDF_LOGE("%s: Fail to mmap the shared memory, errno = %d", __func__, errno); 348 return NULL; 349 } 350 void *pBase = shmat(shmid, NULL, 0); 351 if (pBase == ((void *)-1)) { 352 HDF_LOGE("%s: Fail to attach the shared memory, errno = %d", __func__, errno); 353 return NULL; 354 } 355 ((PriBufferHandle*)buffer)->shmid = shmid; 356 HDF_LOGI("%s: Mmap shared memory succeed", __func__); 357 return pBase; 358} 359 360static void *MmapMmzNoCache(uint64_t paddr, int32_t size) 361{ 362 MmzMemory mmz = {0}; 363 mmz.paddr = paddr; 364 mmz.size = size; 365 SendCmd(MMZ_MAP_NOCACHE_TYPE, (uintptr_t)&mmz); 366 return (void *)mmz.vaddr; 367} 368 369static int32_t UnmapMmz(BufferHandle *buffer) 370{ 371 MmzMemory mmz = {0}; 372 mmz.paddr = buffer->phyAddr; 373 mmz.size = buffer->size; 374 mmz.vaddr = buffer->virAddr; 375 return SendCmd(MMZ_UNMAP_TYPE, (uintptr_t)&mmz); 376} 377 378static void *MmapMmzCache(uint64_t paddr, int32_t size) 379{ 380 MmzMemory mmz = {0}; 381 mmz.paddr = paddr; 382 mmz.size = size; 383 SendCmd(MMZ_MAP_CACHE_TYPE, (uintptr_t)&mmz); 384 return (void *)mmz.vaddr; 385} 386 387static void *MmapCache(BufferHandle *buffer) 388{ 389 CHECK_NULLPOINTER_RETURN_VALUE(buffer, NULL); 390 if ((buffer->size > MAX_MALLOC_SIZE) || (buffer->size == 0)) { 391 HDF_LOGE("%s: size is invalid, buffer->size = %d", __func__, buffer->size); 392 return NULL; 393 } 394 if (buffer->usage == HBM_USE_MEM_MMZ_CACHE) { 395 return MmapMmzCache(buffer->phyAddr, buffer->size); 396 } else { 397 HDF_LOGE("%s: buffer usage error, buffer->usage = 0x%" PRIx64 "", __func__, buffer->usage); 398 return NULL; 399 } 400} 401 402static void *Mmap(BufferHandle *buffer) 403{ 404 CHECK_NULLPOINTER_RETURN_VALUE(buffer, NULL); 405 if ((buffer->size > MAX_MALLOC_SIZE) || (buffer->size == 0)) { 406 HDF_LOGE("%s: size is invalid, buffer->size = %d", __func__, buffer->size); 407 return NULL; 408 } 409 410 switch (buffer->usage) { 411 case HBM_USE_MEM_MMZ_CACHE: 412 return MmapMmzCache(buffer->phyAddr, buffer->size); 413 case HBM_USE_MEM_MMZ: 414 return MmapMmzNoCache(buffer->phyAddr, buffer->size); 415 case HBM_USE_MEM_SHARE: 416 return MmapShm(buffer); 417 default: 418 HDF_LOGE("%s: not support memory usage: 0x%" PRIx64 "", __func__, buffer->usage); 419 break; 420 } 421 return NULL; 422} 423 424static int32_t UnmapShm(BufferHandle *buffer) 425{ 426 if (shmdt(buffer->virAddr) == -1) { 427 HDF_LOGE("%s: Fail to unmap shared memory errno = %d", __func__, errno); 428 return DISPLAY_FAILURE; 429 } 430 int32_t shmid = ((PriBufferHandle*)buffer)->shmid; 431 if ((shmid != INVALID_SHMID) && (shmctl(shmid, IPC_RMID, 0) == -1)) { 432 HDF_LOGE("%s: Fail to free shmid, errno = %d", __func__, errno); 433 } 434 return DISPLAY_SUCCESS; 435} 436 437static int32_t Unmap(BufferHandle *buffer) 438{ 439 int32_t ret; 440 441 CHECK_NULLPOINTER_RETURN_VALUE(buffer, DISPLAY_NULL_PTR); 442 CHECK_NULLPOINTER_RETURN_VALUE(buffer->virAddr, DISPLAY_NULL_PTR); 443 if ((buffer->size > MAX_MALLOC_SIZE) || (buffer->size == 0)) { 444 HDF_LOGE("%s: size is invalid, buffer->size = %d", __func__, buffer->size); 445 return DISPLAY_FAILURE; 446 } 447 switch (buffer->usage) { 448 case HBM_USE_MEM_MMZ_CACHE: 449 case HBM_USE_MEM_MMZ: 450 ret = UnmapMmz(buffer); 451 break; 452 case HBM_USE_MEM_SHARE: 453 ret = UnmapShm(buffer); 454 break; 455 default: 456 HDF_LOGE("%s: not support memory usage: 0x%" PRIx64 "", __func__, buffer->usage); 457 ret = DISPLAY_FAILURE; 458 break; 459 } 460 return ret; 461} 462 463static int32_t FlushCache(BufferHandle *buffer) 464{ 465 int32_t ret; 466 467 CHECK_NULLPOINTER_RETURN_VALUE(buffer, DISPLAY_NULL_PTR); 468 CHECK_NULLPOINTER_RETURN_VALUE(buffer->virAddr, DISPLAY_NULL_PTR); 469 if ((buffer->size > MAX_MALLOC_SIZE) || (buffer->size == 0)) { 470 HDF_LOGE("%s: size is invalid, buffer->size = %d", __func__, buffer->size); 471 return DISPLAY_FAILURE; 472 } 473 if (buffer->usage == HBM_USE_MEM_MMZ_CACHE) { 474 ret = MmzFlushCache(buffer); 475 if (ret != DISPLAY_SUCCESS) { 476 HDF_LOGE("%s: MmzFlushCache failure, ret 0x%x", __func__, ret); 477 return DISPLAY_FAILURE; 478 } 479 } else { 480 HDF_LOGE("%s: buffer usage error, usage = 0x%" PRIx64"", __func__, buffer->usage); 481 return DISPLAY_FAILURE; 482 } 483 return DISPLAY_SUCCESS; 484} 485 486static int32_t InvalidateCache(BufferHandle *buffer) 487{ 488 int32_t ret; 489 490 CHECK_NULLPOINTER_RETURN_VALUE(buffer, DISPLAY_NULL_PTR); 491 CHECK_NULLPOINTER_RETURN_VALUE(buffer->virAddr, DISPLAY_NULL_PTR); 492 if ((buffer->size > MAX_MALLOC_SIZE) || (buffer->size == 0)) { 493 HDF_LOGE("%s: size is invalid, buffer->size = %d", __func__, buffer->size); 494 return DISPLAY_FAILURE; 495 } 496 if (buffer->usage == HBM_USE_MEM_MMZ_CACHE) { 497 ret = MmzInvalidateCache(buffer); 498 if (ret != DISPLAY_SUCCESS) { 499 HDF_LOGE("%s: MmzFlushCache failure, ret 0x%x", __func__, ret); 500 return DISPLAY_FAILURE; 501 } 502 } else { 503 HDF_LOGE("%s: buffer usage error, usage = 0x%" PRIx64"", __func__, buffer->usage); 504 return DISPLAY_FAILURE; 505 } 506 return DISPLAY_SUCCESS; 507} 508 509int32_t GrallocInitialize(GrallocFuncs **funcs) 510{ 511 if (funcs == NULL) { 512 HDF_LOGE("%s: funcs is null", __func__); 513 return DISPLAY_NULL_PTR; 514 } 515 GrallocFuncs *gFuncs = (GrallocFuncs *)malloc(sizeof(GrallocFuncs)); 516 if (gFuncs == NULL) { 517 HDF_LOGE("%s: gFuncs is null", __func__); 518 return DISPLAY_NULL_PTR; 519 } 520 (void)memset_s(gFuncs, sizeof(GrallocFuncs), 0, sizeof(GrallocFuncs)); 521 gFuncs->AllocMem = AllocMem; 522 gFuncs->FreeMem = FreeMem; 523 gFuncs->Mmap = Mmap; 524 gFuncs->MmapCache = MmapCache; 525 gFuncs->Unmap = Unmap; 526 gFuncs->FlushCache = FlushCache; 527 gFuncs->FlushMCache = FlushCache; 528 gFuncs->InvalidateCache = InvalidateCache; 529 *funcs = gFuncs; 530 HDF_LOGI("%s: gralloc initialize success", __func__); 531 return DISPLAY_SUCCESS; 532} 533 534int32_t GrallocUninitialize(GrallocFuncs *funcs) 535{ 536 if (funcs == NULL) { 537 HDF_LOGE("%s: funcs is null", __func__); 538 return DISPLAY_NULL_PTR; 539 } 540 free(funcs); 541 HDF_LOGI("%s: gralloc uninitialize success", __func__); 542 return DISPLAY_SUCCESS; 543} 544