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
22 namespace android {
23 namespace intel {
24
TngGrallocBufferMapper(IMG_gralloc_module_public_t & module,DataBuffer & buffer)25 TngGrallocBufferMapper::TngGrallocBufferMapper(IMG_gralloc_module_public_t& module,
26 DataBuffer& buffer)
27 : GrallocBufferMapperBase(buffer),
28 mIMGGrallocModule(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 ALOGE("%s: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
~TngGrallocBufferMapper()47 TngGrallocBufferMapper::~TngGrallocBufferMapper()
48 {
49 CTRACE();
50
51 if (mClonedHandle == 0)
52 return;
53 native_handle_close(mClonedHandle);
54 native_handle_delete(mClonedHandle);
55 }
56
gttMap(void * vaddr,uint32_t size,uint32_t gttAlign,int * offset)57 bool 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
gttUnmap(void * vaddr)89 bool 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
map()114 bool 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 = mIMGGrallocModule.getCpuAddress(&mIMGGrallocModule,
126 (buffer_handle_t)mClonedHandle,
127 vaddr,
128 size);
129 if (err) {
130 ELOGTRACE("failed to map. err = %d", err);
131 return false;
132 }
133
134 for (i = 0; i < SUB_BUFFER_MAX; i++) {
135 // skip gtt mapping for empty sub buffers
136 if (!vaddr[i] || !size[i])
137 continue;
138
139 // map to gtt
140 ret = gttMap(vaddr[i], size[i], 0, >tOffsetInPage);
141 if (!ret) {
142 VLOGTRACE("failed to map %d into gtt", i);
143 break;
144 }
145
146 mCpuAddress[i] = vaddr[i];
147 mSize[i] = size[i];
148 mGttOffsetInPage[i] = gttOffsetInPage;
149 // TODO: set kernel handle
150 mKHandle[i] = 0;
151 }
152
153 if (i == SUB_BUFFER_MAX) {
154 return true;
155 }
156
157 // error handling
158 for (i = 0; i < SUB_BUFFER_MAX; i++) {
159 if (mCpuAddress[i]) {
160 gttUnmap(mCpuAddress[i]);
161 }
162 }
163
164 err = mIMGGrallocModule.putCpuAddress(&mIMGGrallocModule,
165 (buffer_handle_t)mClonedHandle);
166 return false;
167 }
168
unmap()169 bool TngGrallocBufferMapper::unmap()
170 {
171 int i;
172 int err;
173
174 CTRACE();
175
176 for (i = 0; i < SUB_BUFFER_MAX; i++) {
177 if (mCpuAddress[i])
178 gttUnmap(mCpuAddress[i]);
179
180 mGttOffsetInPage[i] = 0;
181 mCpuAddress[i] = 0;
182 mSize[i] = 0;
183 }
184
185 err = mIMGGrallocModule.putCpuAddress(&mIMGGrallocModule,
186 (buffer_handle_t)mClonedHandle);
187 if (err) {
188 ELOGTRACE("failed to unmap. err = %d", err);
189 }
190 return err;
191 }
192
getKHandle(int subIndex)193 uint32_t TngGrallocBufferMapper::getKHandle(int subIndex)
194 {
195 uint32_t ret = GrallocBufferMapperBase::getKHandle(subIndex);
196 if (subIndex == 0 && ret == 0) {
197 if (mapKhandle())
198 return mKHandle[subIndex];
199 }
200
201 return ret;
202 }
203
mapKhandle()204 bool TngGrallocBufferMapper::mapKhandle()
205 {
206 // TODO: this is a complete hack and temporary workaround
207 // need support from DDK to map khandle
208 void *wsbmBufferObject = 0;
209 int ret = psbWsbmWrapTTMBuffer2(mHandle, &wsbmBufferObject);
210 if (ret != 0) {
211 ELOGTRACE("Wrap ttm buffer failed!");
212 return false;
213 }
214
215 ret = psbWsbmCreateFromUB(wsbmBufferObject, mWidth * mHeight, mCpuAddress[0]);
216 if (ret != 0) {
217 ELOGTRACE("Create from UB failed!");
218 return false;
219 }
220
221 mKHandle[0] = psbWsbmGetKBufHandle(wsbmBufferObject);
222 psbWsbmUnReference(wsbmBufferObject);
223 return true;
224 }
225
getFbHandle(int subIndex)226 uint32_t TngGrallocBufferMapper::getFbHandle(int subIndex)
227 {
228 void *vaddr[SUB_BUFFER_MAX];
229 uint32_t size[SUB_BUFFER_MAX];
230 int err;
231
232 CTRACE();
233
234 if (subIndex < 0 || subIndex >= SUB_BUFFER_MAX) {
235 return 0;
236 }
237
238 // get virtual address
239 err = mIMGGrallocModule.getCpuAddress(&mIMGGrallocModule,
240 (buffer_handle_t)mClonedHandle,
241 vaddr,
242 size);
243 if (err) {
244 ELOGTRACE("failed to map. err = %d", err);
245 return 0;
246 }
247
248 return (uint32_t)vaddr[subIndex];
249 }
250
putFbHandle()251 void TngGrallocBufferMapper::putFbHandle()
252 {
253 int err = mIMGGrallocModule.putCpuAddress(&mIMGGrallocModule,
254 (buffer_handle_t)mClonedHandle);
255 if (err) {
256 ELOGTRACE("failed to unmap. err = %d", err);
257 }
258 return;
259
260 }
261
262 } // namespace intel
263 } // namespace android
264