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, &gttOffsetInPage);
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