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 <math.h>
17#include <HwcTrace.h>
18#include <Drm.h>
19#include <Hwcomposer.h>
20#include <tangier/TngOverlayPlane.h>
21#include <tangier/TngGrallocBuffer.h>
22
23namespace android {
24namespace intel {
25
26TngOverlayPlane::TngOverlayPlane(int index, int disp)
27    : OverlayPlaneBase(index, disp),
28      mRotationBufProvider(NULL)
29{
30    CTRACE();
31
32    memset(&mContext, 0, sizeof(mContext));
33}
34
35TngOverlayPlane::~TngOverlayPlane()
36{
37    CTRACE();
38}
39
40bool TngOverlayPlane::flip(void *ctx)
41{
42    RETURN_FALSE_IF_NOT_INIT();
43
44    if (!DisplayPlane::flip(ctx))
45        return false;
46
47    mContext.type = DC_OVERLAY_PLANE;
48    mContext.ctx.ov_ctx.ovadd = 0x0;
49    mContext.ctx.ov_ctx.ovadd = (mBackBuffer[mCurrent]->gttOffsetInPage << 12);
50    mContext.ctx.ov_ctx.index = mIndex;
51    mContext.ctx.ov_ctx.pipe = mDevice;
52    mContext.ctx.ov_ctx.ovadd |= mPipeConfig;
53    mContext.ctx.ov_ctx.ovadd |= 0x1;
54
55    // move to next back buffer
56    //mCurrent = (mCurrent + 1) % OVERLAY_BACK_BUFFER_COUNT;
57
58    VTRACE("ovadd = %#x, index = %d, device = %d",
59          mContext.ctx.ov_ctx.ovadd,
60          mIndex,
61          mDevice);
62
63    return true;
64}
65
66bool TngOverlayPlane::reset()
67{
68    OverlayPlaneBase::reset();
69    if (mRotationBufProvider)
70        mRotationBufProvider->reset();
71    return true;
72}
73
74void* TngOverlayPlane::getContext() const
75{
76    CTRACE();
77    return (void *)&mContext;
78}
79
80bool TngOverlayPlane::setDataBuffer(BufferMapper& mapper)
81{
82    if (OverlayPlaneBase::setDataBuffer(mapper) == false) {
83        return false;
84    }
85
86    if (mIsProtectedBuffer) {
87        // Bit 0: Decryption request, only allowed to change on a synchronous flip
88        // This request will be qualified with the separate decryption enable bit for OV
89        mBackBuffer[mCurrent]->buf->OSTART_0Y |= 0x1;
90        mBackBuffer[mCurrent]->buf->OSTART_1Y |= 0x1;
91    }
92
93    mContext.gtt_key = (uint64_t)mapper.getCpuAddress(0);
94    return true;
95}
96
97bool TngOverlayPlane::initialize(uint32_t bufferCount)
98{
99    if (!OverlayPlaneBase::initialize(bufferCount)) {
100        ETRACE("failed to initialize OverlayPlaneBase");
101        return false;
102    }
103
104    // setup rotation buffer
105    mRotationBufProvider = new RotationBufferProvider(mWsbm);
106    if (!mRotationBufProvider || !mRotationBufProvider->initialize()) {
107        DEINIT_AND_RETURN_FALSE("failed to initialize RotationBufferProvider");
108    }
109    return true;
110}
111
112void TngOverlayPlane::deinitialize()
113{
114    DEINIT_AND_DELETE_OBJ(mRotationBufProvider);
115    OverlayPlaneBase::deinitialize();
116}
117
118bool TngOverlayPlane::rotatedBufferReady(BufferMapper& mapper, BufferMapper* &rotatedMapper)
119{
120    struct VideoPayloadBuffer *payload;
121    VideoPayloadBuffer buffer_info;
122    uint32_t format;
123    // only NV12_VED has rotated buffer
124    format = mapper.getFormat();
125
126    if (format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar &&
127        format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled &&
128        format != HAL_PIXEL_FORMAT_NV12) {
129        ETRACE("Invalid video format %#x", format);
130        return false;
131    }
132
133    payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1);
134
135    if (payload == NULL && format == HAL_PIXEL_FORMAT_NV12) {
136         // need to populate buffer_info
137        void *p = mapper.getCpuAddress(SUB_BUFFER0);
138        if (!p) {
139            ETRACE("failed to get buffer user pointer");
140            return false;
141        }
142
143        bool ret = mRotationBufProvider->prepareBufferInfo(mapper.getWidth(),
144                                                mapper.getHeight(),
145                                                mapper.getStride().yuv.yStride,
146                                                &buffer_info, p);
147        if (ret == false) {
148            ETRACE("failed to prepare buffer info");
149            return false;
150        }
151        payload = &buffer_info;
152    }
153
154    // check payload
155    if (!payload) {
156        ETRACE("no payload found");
157        return false;
158    }
159
160    if (payload->force_output_method == FORCE_OUTPUT_GPU) {
161        ETRACE("Output method is not supported!");
162        return false;
163    }
164
165    if (payload->client_transform != mTransform ||
166        mBobDeinterlace) {
167        payload->hwc_timestamp = systemTime();
168        payload->layer_transform = mTransform;
169        if (!mRotationBufProvider->setupRotationBuffer(payload, mTransform)) {
170            ETRACE("failed to setup rotation buffer");
171            return false;
172        }
173    }
174
175    rotatedMapper = getTTMMapper(mapper, payload);
176
177    return true;
178}
179
180bool TngOverlayPlane::flush(uint32_t flags)
181{
182    RETURN_FALSE_IF_NOT_INIT();
183    ATRACE("flags = %#x, type = %d, index = %d", flags, mType, mIndex);
184
185    if (!(flags & PLANE_ENABLE) && !(flags & PLANE_DISABLE))
186        return false;
187
188    struct drm_psb_register_rw_arg arg;
189    memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
190
191    if (flags & PLANE_DISABLE)
192        arg.plane_disable_mask = 1;
193    else if (flags & PLANE_ENABLE)
194        arg.plane_enable_mask = 1;
195
196    arg.plane.type = DC_OVERLAY_PLANE;
197    arg.plane.index = mIndex;
198    arg.plane.ctx = (mBackBuffer[mCurrent]->gttOffsetInPage << 12);
199    // pipe select
200    arg.plane.ctx |= mPipeConfig;
201
202    if (flags & PLANE_DISABLE) {
203        DTRACE("disabling overlay %d on device %d", mIndex, mDevice);
204    }
205
206    // issue ioctl
207    Drm *drm = Hwcomposer::getInstance().getDrm();
208    bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
209    if (ret == false) {
210        WTRACE("overlay update failed with error code %d", ret);
211        return false;
212    }
213
214    return true;
215}
216
217} // namespace intel
218} // namespace android
219