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(gralloc_module_t const & module,DataBuffer & buffer)25 TngGrallocBufferMapper::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
~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 = 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
unmap()171 bool 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
getKHandle(int subIndex)196 uint32_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
mapKhandle()207 bool 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
getFbHandle(int subIndex)229 uint32_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
putFbHandle()255 void 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