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(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
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 = 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
169bool 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
193uint32_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
204bool 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
226uint32_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
251void 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