1/* 2// Copyright (c) 2014 Intel Corporation 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// http://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15*/ 16#include <common/utils/HwcTrace.h> 17#include <common/base/Drm.h> 18#include <Hwcomposer.h> 19#include <ips/tangier/TngGrallocBufferMapper.h> 20#include <ips/common/WsbmWrapper.h> 21 22namespace android { 23namespace intel { 24 25TngGrallocBufferMapper::TngGrallocBufferMapper(gralloc_module_t const& module, 26 DataBuffer& buffer) 27 : GrallocBufferMapperBase(buffer), 28 mGrallocModule(module), 29 mBufferObject(0) 30{ 31 CTRACE(); 32 33 const native_handle_t *h = (native_handle_t *)mHandle; 34 35 mClonedHandle = native_handle_create(h->numFds, h->numInts); 36 if (mClonedHandle == 0) { 37 ELOGTRACE("Failed to create handle, out of memory!"); 38 return; 39 } 40 for (int i = 0; i < h->numFds; i++) 41 { 42 mClonedHandle->data[i] = (h->data[i] >= 0) ? dup(h->data[i]) : -1; 43 } 44 memcpy(mClonedHandle->data + h->numFds, h->data + h->numFds, h->numInts*sizeof(int)); 45} 46 47TngGrallocBufferMapper::~TngGrallocBufferMapper() 48{ 49 CTRACE(); 50 51 if (mClonedHandle == 0) 52 return; 53 native_handle_close(mClonedHandle); 54 native_handle_delete(mClonedHandle); 55} 56 57bool TngGrallocBufferMapper::gttMap(void *vaddr, 58 uint32_t size, 59 uint32_t gttAlign, 60 int *offset) 61{ 62 struct psb_gtt_mapping_arg arg; 63 bool ret; 64 65 ALOGTRACE("vaddr = %p, size = %d", vaddr, size); 66 67 if (!vaddr || !size || !offset) { 68 VLOGTRACE("invalid parameters"); 69 return false; 70 } 71 72 arg.type = PSB_GTT_MAP_TYPE_VIRTUAL; 73 arg.page_align = gttAlign; 74 arg.vaddr = (uint32_t)vaddr; 75 arg.size = size; 76 77 Drm *drm = Hwcomposer::getInstance().getDrm(); 78 ret = drm->writeReadIoctl(DRM_PSB_GTT_MAP, &arg, sizeof(arg)); 79 if (ret == false) { 80 ELOGTRACE("gtt mapping failed"); 81 return false; 82 } 83 84 VLOGTRACE("offset = %#x", arg.offset_pages); 85 *offset = arg.offset_pages; 86 return true; 87} 88 89bool TngGrallocBufferMapper::gttUnmap(void *vaddr) 90{ 91 struct psb_gtt_mapping_arg arg; 92 bool ret; 93 94 ALOGTRACE("vaddr = %p", vaddr); 95 96 if (!vaddr) { 97 ELOGTRACE("invalid parameter"); 98 return false; 99 } 100 101 arg.type = PSB_GTT_MAP_TYPE_VIRTUAL; 102 arg.vaddr = (uint32_t)vaddr; 103 104 Drm *drm = Hwcomposer::getInstance().getDrm(); 105 ret = drm->writeIoctl(DRM_PSB_GTT_UNMAP, &arg, sizeof(arg)); 106 if (ret == false) { 107 ELOGTRACE("gtt unmapping failed"); 108 return false; 109 } 110 111 return true; 112} 113 114bool TngGrallocBufferMapper::map() 115{ 116 void *vaddr[SUB_BUFFER_MAX]; 117 uint32_t size[SUB_BUFFER_MAX]; 118 int gttOffsetInPage = 0; 119 bool ret; 120 int err; 121 int i; 122 123 CTRACE(); 124 // get virtual address 125 err = mGrallocModule.perform(&mGrallocModule, 126 GRALLOC_MODULE_GET_BUFFER_CPU_ADDRESSES_IMG, 127 (buffer_handle_t)mClonedHandle, 128 vaddr, 129 size); 130 if (err) { 131 ELOGTRACE("failed to map. err = %d", err); 132 return false; 133 } 134 135 for (i = 0; i < SUB_BUFFER_MAX; i++) { 136 // skip gtt mapping for empty sub buffers 137 if (!vaddr[i] || !size[i]) 138 continue; 139 140 // map to gtt 141 ret = gttMap(vaddr[i], size[i], 0, >tOffsetInPage); 142 if (!ret) { 143 VLOGTRACE("failed to map %d into gtt", i); 144 break; 145 } 146 147 mCpuAddress[i] = vaddr[i]; 148 mSize[i] = size[i]; 149 mGttOffsetInPage[i] = gttOffsetInPage; 150 // TODO: set kernel handle 151 mKHandle[i] = 0; 152 } 153 154 if (i == SUB_BUFFER_MAX) { 155 return true; 156 } 157 158 // error handling 159 for (i = 0; i < SUB_BUFFER_MAX; i++) { 160 if (mCpuAddress[i]) { 161 gttUnmap(mCpuAddress[i]); 162 } 163 } 164 165 err = mGrallocModule.perform(&mGrallocModule, 166 GRALLOC_MODULE_PUT_BUFFER_CPU_ADDRESSES_IMG, 167 (buffer_handle_t)mClonedHandle); 168 return false; 169} 170 171bool TngGrallocBufferMapper::unmap() 172{ 173 int i; 174 int err; 175 176 CTRACE(); 177 178 for (i = 0; i < SUB_BUFFER_MAX; i++) { 179 if (mCpuAddress[i]) 180 gttUnmap(mCpuAddress[i]); 181 182 mGttOffsetInPage[i] = 0; 183 mCpuAddress[i] = 0; 184 mSize[i] = 0; 185 } 186 187 err = mGrallocModule.perform(&mGrallocModule, 188 GRALLOC_MODULE_PUT_BUFFER_CPU_ADDRESSES_IMG, 189 (buffer_handle_t)mClonedHandle); 190 if (err) { 191 ELOGTRACE("failed to unmap. err = %d", err); 192 } 193 return err; 194} 195 196uint32_t TngGrallocBufferMapper::getKHandle(int subIndex) 197{ 198 uint32_t ret = GrallocBufferMapperBase::getKHandle(subIndex); 199 if (subIndex == 0 && ret == 0) { 200 if (mapKhandle()) 201 return mKHandle[subIndex]; 202 } 203 204 return ret; 205} 206 207bool TngGrallocBufferMapper::mapKhandle() 208{ 209 // TODO: this is a complete hack and temporary workaround 210 // need support from DDK to map khandle 211 void *wsbmBufferObject = 0; 212 int ret = psbWsbmWrapTTMBuffer2(mHandle, &wsbmBufferObject); 213 if (ret != 0) { 214 ELOGTRACE("Wrap ttm buffer failed!"); 215 return false; 216 } 217 218 ret = psbWsbmCreateFromUB(wsbmBufferObject, mWidth * mHeight, mCpuAddress[0]); 219 if (ret != 0) { 220 ELOGTRACE("Create from UB failed!"); 221 return false; 222 } 223 224 mKHandle[0] = psbWsbmGetKBufHandle(wsbmBufferObject); 225 psbWsbmUnReference(wsbmBufferObject); 226 return true; 227} 228 229uint32_t TngGrallocBufferMapper::getFbHandle(int subIndex) 230{ 231 void *vaddr[SUB_BUFFER_MAX]; 232 uint32_t size[SUB_BUFFER_MAX]; 233 int err; 234 235 CTRACE(); 236 237 if (subIndex < 0 || subIndex >= SUB_BUFFER_MAX) { 238 return 0; 239 } 240 241 // get virtual address 242 err = mGrallocModule.perform(&mGrallocModule, 243 GRALLOC_MODULE_GET_BUFFER_CPU_ADDRESSES_IMG, 244 (buffer_handle_t)mClonedHandle, 245 vaddr, 246 size); 247 if (err) { 248 ELOGTRACE("failed to map. err = %d", err); 249 return 0; 250 } 251 252 return (uint32_t)vaddr[subIndex]; 253} 254 255void TngGrallocBufferMapper::putFbHandle() 256{ 257 int err = mGrallocModule.perform(&mGrallocModule, 258 GRALLOC_MODULE_PUT_BUFFER_CPU_ADDRESSES_IMG, 259 (buffer_handle_t)mClonedHandle); 260 if (err) { 261 ELOGTRACE("failed to unmap. err = %d", err); 262 } 263 return; 264 265} 266 267} // namespace intel 268} // namespace android 269