1ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/* 2ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * Copyright (C) 2008 The Android Open Source Project 315c7eb9ba46119290695b650d23180884f1156faArun Kumar K.R * Copyright (c) 2010-2012,2014 The Linux Foundation. All rights reserved. 4ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * 5ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 6ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * you may not use this file except in compliance with the License. 7ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * You may obtain a copy of the License at 8ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * 9ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * http://www.apache.org/licenses/LICENSE-2.0 10ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * 11ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * Unless required by applicable law or agreed to in writing, software 12ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * distributed under the License is distributed on an "AS IS" BASIS, 13ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * See the License for the specific language governing permissions and 15ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * limitations under the License. 16ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson */ 17ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 18ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <sys/mman.h> 19ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 20ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <cutils/log.h> 21ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <cutils/properties.h> 22ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <dlfcn.h> 23ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 24ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <hardware/hardware.h> 25ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 26ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <fcntl.h> 27ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <errno.h> 28ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <sys/ioctl.h> 29ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <string.h> 30ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <stdlib.h> 31ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <pthread.h> 32ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <cutils/atomic.h> 33ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 34ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <linux/fb.h> 35ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <linux/msm_mdp.h> 36ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 37ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <GLES/gl.h> 38ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 39ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include "gralloc_priv.h" 40ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include "fb_priv.h" 41ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include "gr.h" 42ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <cutils/properties.h> 43ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <profiler.h> 44ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 45ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#define EVEN_OUT(x) if (x & 0x0001) {x--;} 46ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/** min of int a, b */ 47ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic inline int min(int a, int b) { 48ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson return (a<b) ? a : b; 49ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson} 50ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/** max of int a, b */ 51ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic inline int max(int a, int b) { 52ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson return (a>b) ? a : b; 53ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson} 54ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 55ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonenum { 56ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson PAGE_FLIP = 0x00000001, 57ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}; 58ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 59ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstruct fb_context_t { 60ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson framebuffer_device_t device; 61ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}; 62ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 63ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 64ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int fb_setSwapInterval(struct framebuffer_device_t* dev, 65ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson int interval) 66ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{ 67ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson //XXX: Get the value here and implement along with 68ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson //single vsync in HWC 69ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson char pval[PROPERTY_VALUE_MAX]; 70ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson property_get("debug.egl.swapinterval", pval, "-1"); 71ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson int property_interval = atoi(pval); 72ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson if (property_interval >= 0) 73ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson interval = property_interval; 74ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 75ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson private_module_t* m = reinterpret_cast<private_module_t*>( 76ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson dev->common.module); 77ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson if (interval < dev->minSwapInterval || interval > dev->maxSwapInterval) 78ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson return -EINVAL; 79ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 80ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson m->swapInterval = interval; 81ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson return 0; 82ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson} 83ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 84ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) 85ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{ 86ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson private_module_t* m = 87ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson reinterpret_cast<private_module_t*>(dev->common.module); 88ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson private_handle_t *hnd = static_cast<private_handle_t*> 89ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson (const_cast<native_handle_t*>(buffer)); 9092e456fd92a6231dbf5d9de5289ed2f84841a804Saurabh Shah const unsigned int offset = (unsigned int) (hnd->base - 9192e456fd92a6231dbf5d9de5289ed2f84841a804Saurabh Shah m->framebuffer->base); 92ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson m->info.activate = FB_ACTIVATE_VBL; 9315c7eb9ba46119290695b650d23180884f1156faArun Kumar K.R m->info.yoffset = (int)(offset / m->finfo.line_length); 94ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) { 95ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson ALOGE("%s: FBIOPUT_VSCREENINFO for primary failed, str: %s", 96ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson __FUNCTION__, strerror(errno)); 97ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson return -errno; 98ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson } 99ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson return 0; 100ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson} 101ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 102ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int fb_compositionComplete(struct framebuffer_device_t* dev) 103ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{ 104ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson // TODO: Properly implement composition complete callback 10515c7eb9ba46119290695b650d23180884f1156faArun Kumar K.R if(!dev) { 10615c7eb9ba46119290695b650d23180884f1156faArun Kumar K.R return -1; 10715c7eb9ba46119290695b650d23180884f1156faArun Kumar K.R } 108ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson glFinish(); 109ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 110ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson return 0; 111ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson} 112ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 113ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonint mapFrameBufferLocked(struct private_module_t* module) 114ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{ 115ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson // already initialized... 116ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson if (module->framebuffer) { 117ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson return 0; 118ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson } 119ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson char const * const device_template[] = { 120ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson "/dev/graphics/fb%u", 121ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson "/dev/fb%u", 122ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 0 }; 123ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 124ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson int fd = -1; 125ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson int i=0; 126ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson char name[64]; 127ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson char property[PROPERTY_VALUE_MAX]; 128ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 129ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson while ((fd==-1) && device_template[i]) { 130ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson snprintf(name, 64, device_template[i], 0); 131ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson fd = open(name, O_RDWR, 0); 132ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson i++; 133ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson } 134ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson if (fd < 0) 135ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson return -errno; 136ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 137ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson memset(&module->commit, 0, sizeof(struct mdp_display_commit)); 138ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 139ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson struct fb_fix_screeninfo finfo; 140a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) { 141a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson close(fd); 142ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson return -errno; 143a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson } 144ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 145ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson struct fb_var_screeninfo info; 146a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) { 147a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson close(fd); 148ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson return -errno; 149a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson } 150ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 151ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.reserved[0] = 0; 152ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.reserved[1] = 0; 153ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.reserved[2] = 0; 154ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.xoffset = 0; 155ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.yoffset = 0; 156ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.activate = FB_ACTIVATE_NOW; 157ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 158ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson /* Interpretation of offset for color fields: All offsets are from the 159ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * right, inside a "pixel" value, which is exactly 'bits_per_pixel' wide 160ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * (means: you can use the offset as right argument to <<). A pixel 161ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * afterwards is a bit stream and is written to video memory as that 162ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * unmodified. This implies big-endian byte order if bits_per_pixel is 163ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * greater than 8. 164ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson */ 165ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 166ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson if(info.bits_per_pixel == 32) { 167ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson /* 168ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * Explicitly request RGBA_8888 169ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson */ 170ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.bits_per_pixel = 32; 171ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.red.offset = 24; 172ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.red.length = 8; 173ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.green.offset = 16; 174ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.green.length = 8; 175ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.blue.offset = 8; 176ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.blue.length = 8; 177ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.transp.offset = 0; 178ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.transp.length = 8; 179ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 180ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson /* Note: the GL driver does not have a r=8 g=8 b=8 a=0 config, so if we 181ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * do not use the MDP for composition (i.e. hw composition == 0), ask 182ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * for RGBA instead of RGBX. */ 183ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson if (property_get("debug.sf.hw", property, NULL) > 0 && 184ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson atoi(property) == 0) 185ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888; 186ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson else if(property_get("debug.composition.type", property, NULL) > 0 && 187ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson (strncmp(property, "mdp", 3) == 0)) 188ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888; 189ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson else 190ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson module->fbFormat = HAL_PIXEL_FORMAT_RGBA_8888; 191ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson } else { 192ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson /* 193ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * Explicitly request 5/6/5 194ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson */ 195ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.bits_per_pixel = 16; 196ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.red.offset = 11; 197ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.red.length = 5; 198ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.green.offset = 5; 199ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.green.length = 6; 200ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.blue.offset = 0; 201ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.blue.length = 5; 202ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.transp.offset = 0; 203ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.transp.length = 0; 204ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson module->fbFormat = HAL_PIXEL_FORMAT_RGB_565; 205ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson } 206ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 207ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson //adreno needs 4k aligned offsets. Max hole size is 4096-1 20892e456fd92a6231dbf5d9de5289ed2f84841a804Saurabh Shah unsigned int size = roundUpToPageSize(info.yres * info.xres * 20915c7eb9ba46119290695b650d23180884f1156faArun Kumar K.R (info.bits_per_pixel/8)); 210ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 211ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson /* 212ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * Request NUM_BUFFERS screens (at least 2 for page flipping) 213ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson */ 214ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson int numberOfBuffers = (int)(finfo.smem_len/size); 215ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson ALOGV("num supported framebuffers in kernel = %d", numberOfBuffers); 216ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 217ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson if (property_get("debug.gr.numframebuffers", property, NULL) > 0) { 218ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson int num = atoi(property); 219ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson if ((num >= NUM_FRAMEBUFFERS_MIN) && (num <= NUM_FRAMEBUFFERS_MAX)) { 220ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson numberOfBuffers = num; 221ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson } 222ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson } 223ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson if (numberOfBuffers > NUM_FRAMEBUFFERS_MAX) 224ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson numberOfBuffers = NUM_FRAMEBUFFERS_MAX; 225ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 226ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson ALOGV("We support %d buffers", numberOfBuffers); 227ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 228ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson //consider the included hole by 4k alignment 229ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson uint32_t line_length = (info.xres * info.bits_per_pixel / 8); 23015c7eb9ba46119290695b650d23180884f1156faArun Kumar K.R info.yres_virtual = (uint32_t) ((size * numberOfBuffers) / line_length); 231ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 232ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson uint32_t flags = PAGE_FLIP; 233ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 234ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson if (info.yres_virtual < ((size * 2) / line_length) ) { 235ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson // we need at least 2 for page-flipping 23615c7eb9ba46119290695b650d23180884f1156faArun Kumar K.R info.yres_virtual = (int)(size / line_length); 237ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson flags &= ~PAGE_FLIP; 238ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson ALOGW("page flipping not supported (yres_virtual=%d, requested=%d)", 239ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.yres_virtual, info.yres*2); 240ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson } 241ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 242a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) { 243a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson close(fd); 244ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson return -errno; 245a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson } 246ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 247ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson if (int(info.width) <= 0 || int(info.height) <= 0) { 248ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson // the driver doesn't return that information 249ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson // default to 160 dpi 25015c7eb9ba46119290695b650d23180884f1156faArun Kumar K.R info.width = (uint32_t)(((float)(info.xres) * 25.4f)/160.0f + 0.5f); 25115c7eb9ba46119290695b650d23180884f1156faArun Kumar K.R info.height = (uint32_t)(((float)(info.yres) * 25.4f)/160.0f + 0.5f); 252ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson } 253ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 25415c7eb9ba46119290695b650d23180884f1156faArun Kumar K.R float xdpi = ((float)(info.xres) * 25.4f) / (float)info.width; 25515c7eb9ba46119290695b650d23180884f1156faArun Kumar K.R float ydpi = ((float)(info.yres) * 25.4f) / (float)info.height; 25615c7eb9ba46119290695b650d23180884f1156faArun Kumar K.R 257ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#ifdef MSMFB_METADATA_GET 258ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson struct msmfb_metadata metadata; 259ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson memset(&metadata, 0 , sizeof(metadata)); 260ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson metadata.op = metadata_op_frame_rate; 261ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson if (ioctl(fd, MSMFB_METADATA_GET, &metadata) == -1) { 262ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson ALOGE("Error retrieving panel frame rate"); 263a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson close(fd); 264ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson return -errno; 265ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson } 26615c7eb9ba46119290695b650d23180884f1156faArun Kumar K.R float fps = (float)metadata.data.panel_frame_rate; 267ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#else 268ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson //XXX: Remove reserved field usage on all baselines 269ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson //The reserved[3] field is used to store FPS by the driver. 270ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson float fps = info.reserved[3] & 0xFF; 271ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#endif 272ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson ALOGI("using (fd=%d)\n" 273ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson "id = %s\n" 274ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson "xres = %d px\n" 275ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson "yres = %d px\n" 276ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson "xres_virtual = %d px\n" 277ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson "yres_virtual = %d px\n" 278ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson "bpp = %d\n" 279ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson "r = %2u:%u\n" 280ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson "g = %2u:%u\n" 281ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson "b = %2u:%u\n", 282ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson fd, 283ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson finfo.id, 284ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.xres, 285ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.yres, 286ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.xres_virtual, 287ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.yres_virtual, 288ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.bits_per_pixel, 289ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.red.offset, info.red.length, 290ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.green.offset, info.green.length, 291ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.blue.offset, info.blue.length 292ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson ); 293ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 294ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson ALOGI("width = %d mm (%f dpi)\n" 295ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson "height = %d mm (%f dpi)\n" 296ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson "refresh rate = %.2f Hz\n", 297ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.width, xdpi, 298ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson info.height, ydpi, 299ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson fps 300ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson ); 301ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 302ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 303a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) { 304a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson close(fd); 305ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson return -errno; 306a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson } 307ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 308a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson if (finfo.smem_len <= 0) { 309a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson close(fd); 310ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson return -errno; 311a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson } 312ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 313ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson module->flags = flags; 314ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson module->info = info; 315ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson module->finfo = finfo; 316ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson module->xdpi = xdpi; 317ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson module->ydpi = ydpi; 318ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson module->fps = fps; 319ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson module->swapInterval = 1; 320ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 321ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson CALC_INIT(); 322ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 323ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson /* 324ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * map the framebuffer 325ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson */ 326ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 327ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson module->numBuffers = info.yres_virtual / info.yres; 328ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson module->bufferMask = 0; 329ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson //adreno needs page aligned offsets. Align the fbsize to pagesize. 33092e456fd92a6231dbf5d9de5289ed2f84841a804Saurabh Shah unsigned int fbSize = roundUpToPageSize(finfo.line_length * info.yres)* 331ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson module->numBuffers; 332ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson module->framebuffer = new private_handle_t(fd, fbSize, 333ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson private_handle_t::PRIV_FLAGS_USES_ION, 334ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson BUFFER_TYPE_UI, 335ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson module->fbFormat, info.xres, info.yres); 336ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 337ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson if (vaddr == MAP_FAILED) { 338ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson ALOGE("Error mapping the framebuffer (%s)", strerror(errno)); 339a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson close(fd); 340ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson return -errno; 341ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson } 34292e456fd92a6231dbf5d9de5289ed2f84841a804Saurabh Shah module->framebuffer->base = uint64_t(vaddr); 343ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson memset(vaddr, 0, fbSize); 344ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson //Enable vsync 345ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson int enable = 1; 346ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson ioctl(module->framebuffer->fd, MSMFB_OVERLAY_VSYNC_CTRL, 347ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson &enable); 348ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson return 0; 349ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson} 350ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 351ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int mapFrameBuffer(struct private_module_t* module) 352ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{ 353ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson int err = -1; 354ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson char property[PROPERTY_VALUE_MAX]; 355ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson if((property_get("debug.gralloc.map_fb_memory", property, NULL) > 0) && 356ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson (!strncmp(property, "1", PROPERTY_VALUE_MAX ) || 357ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) { 358ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson pthread_mutex_lock(&module->lock); 359ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson err = mapFrameBufferLocked(module); 360ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson pthread_mutex_unlock(&module->lock); 361ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson } 362ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson return err; 363ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson} 364ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 365ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/*****************************************************************************/ 366ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 367ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int fb_close(struct hw_device_t *dev) 368ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{ 369ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson fb_context_t* ctx = (fb_context_t*)dev; 370ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson if (ctx) { 371a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson //Hack until fbdev is removed. Framework could close this causing hwc a 372a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson //pain. 373a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson //free(ctx); 374ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson } 375ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson return 0; 376ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson} 377ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 378ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonint fb_device_open(hw_module_t const* module, const char* name, 379ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson hw_device_t** device) 380ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{ 381ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson int status = -EINVAL; 382ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson if (!strcmp(name, GRALLOC_HARDWARE_FB0)) { 383ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson alloc_device_t* gralloc_device; 384ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson status = gralloc_open(module, &gralloc_device); 385ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson if (status < 0) 386ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson return status; 387ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 388ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson /* initialize our state here */ 389ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev)); 390a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson if(dev == NULL) { 391a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson gralloc_close(gralloc_device); 392a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson return status; 393a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson } 394ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson memset(dev, 0, sizeof(*dev)); 395ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 396ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson /* initialize the procs */ 397ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson dev->device.common.tag = HARDWARE_DEVICE_TAG; 398ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson dev->device.common.version = 0; 399ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson dev->device.common.module = const_cast<hw_module_t*>(module); 400ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson dev->device.common.close = fb_close; 401ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson dev->device.setSwapInterval = fb_setSwapInterval; 402ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson dev->device.post = fb_post; 403ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson dev->device.setUpdateRect = 0; 404ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson dev->device.compositionComplete = fb_compositionComplete; 405ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 406ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson private_module_t* m = (private_module_t*)module; 407ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson status = mapFrameBuffer(m); 408ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson if (status >= 0) { 409ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3); 410ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson const_cast<uint32_t&>(dev->device.flags) = 0; 411ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson const_cast<uint32_t&>(dev->device.width) = m->info.xres; 412ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson const_cast<uint32_t&>(dev->device.height) = m->info.yres; 413ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson const_cast<int&>(dev->device.stride) = stride; 414ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson const_cast<int&>(dev->device.format) = m->fbFormat; 415ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson const_cast<float&>(dev->device.xdpi) = m->xdpi; 416ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson const_cast<float&>(dev->device.ydpi) = m->ydpi; 417ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson const_cast<float&>(dev->device.fps) = m->fps; 418ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson const_cast<int&>(dev->device.minSwapInterval) = 419ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson PRIV_MIN_SWAP_INTERVAL; 420ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson const_cast<int&>(dev->device.maxSwapInterval) = 421ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson PRIV_MAX_SWAP_INTERVAL; 422ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson const_cast<int&>(dev->device.numFramebuffers) = m->numBuffers; 423ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson dev->device.setUpdateRect = 0; 424ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 425ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson *device = &dev->device.common; 426ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson } 427ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson 428ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson // Close the gralloc module 429ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson gralloc_close(gralloc_device); 430ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson } 431ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson return status; 432ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson} 433