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 <HwcTrace.h>
17#include <Drm.h>
18#include <tangier/TngPrimaryPlane.h>
19#include <tangier/TngGrallocBuffer.h>
20#include <common/PixelFormat.h>
21
22namespace android {
23namespace intel {
24
25TngPrimaryPlane::TngPrimaryPlane(int index, int disp)
26    : TngSpritePlane(index, disp)
27{
28    CTRACE();
29    mType = PLANE_PRIMARY;
30    mForceBottom = true;
31    mAbovePrimary = false;
32}
33
34TngPrimaryPlane::~TngPrimaryPlane()
35{
36    CTRACE();
37}
38
39void TngPrimaryPlane::setFramebufferTarget(buffer_handle_t handle)
40{
41    CTRACE();
42
43    // do not need to update the buffer handle
44    if (mCurrentDataBuffer != handle)
45        mUpdateMasks |= PLANE_BUFFER_CHANGED;
46    else
47        mUpdateMasks &= ~PLANE_BUFFER_CHANGED;
48
49    // if no update then do Not need set data buffer
50    if (!mUpdateMasks)
51        return;
52
53    // don't need to map data buffer for primary plane
54    mContext.type = DC_PRIMARY_PLANE;
55    mContext.ctx.prim_ctx.update_mask = SPRITE_UPDATE_ALL;
56    mContext.ctx.prim_ctx.index = mIndex;
57    mContext.ctx.prim_ctx.pipe = mDevice;
58    mContext.ctx.prim_ctx.stride = align_to((4 * align_to(mPosition.w, 32)), 64);
59#ifdef ENABLE_ROTATION_180
60    mContext.ctx.prim_ctx.linoff = (mPosition.h - 1) * mContext.ctx.prim_ctx.stride + (mPosition.w  - 1)* 4;
61#else
62    mContext.ctx.prim_ctx.linoff = 0;
63#endif
64    mContext.ctx.prim_ctx.pos = 0;
65    mContext.ctx.prim_ctx.size =
66        ((mPosition.h - 1) & 0xfff) << 16 | ((mPosition.w - 1) & 0xfff);
67    mContext.ctx.prim_ctx.surf = 0;
68    mContext.ctx.prim_ctx.contalpa = 0;
69
70    mContext.ctx.prim_ctx.cntr = PixelFormat::PLANE_PIXEL_FORMAT_BGRA8888;
71#ifdef ENABLE_ROTATION_180
72    mContext.ctx.prim_ctx.cntr |= 0x80008000;
73#else
74    mContext.ctx.prim_ctx.cntr |= 0x80000000;
75#endif
76    mCurrentDataBuffer = handle;
77}
78
79bool TngPrimaryPlane::enablePlane(bool enabled)
80{
81    RETURN_FALSE_IF_NOT_INIT();
82
83    struct drm_psb_register_rw_arg arg;
84    memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
85    if (enabled) {
86        arg.plane_enable_mask = 1;
87    } else {
88        arg.plane_disable_mask = 1;
89    }
90    arg.plane.type = DC_PRIMARY_PLANE;
91    arg.plane.index = mIndex;
92    arg.plane.ctx = 0;
93
94    // issue ioctl
95    Drm *drm = Hwcomposer::getInstance().getDrm();
96    bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
97    if (ret == false) {
98        WTRACE("primary enabling (%d) failed with error code %d", enabled, ret);
99        return false;
100    }
101
102    return true;
103
104}
105
106bool TngPrimaryPlane::setDataBuffer(buffer_handle_t handle)
107{
108    if (!handle) {
109        setFramebufferTarget(handle);
110        return true;
111    }
112
113    TngGrallocBuffer tmpBuf(handle);
114    uint32_t usage;
115    bool ret;
116
117    ATRACE("handle = %#x", handle);
118
119    usage = tmpBuf.getUsage();
120    if (GRALLOC_USAGE_HW_FB & usage) {
121        setFramebufferTarget(handle);
122        return true;
123    }
124
125    // use primary as a sprite
126    ret = DisplayPlane::setDataBuffer(handle);
127    if (ret == false) {
128        ETRACE("failed to set data buffer");
129        return ret;
130    }
131
132    mContext.type = DC_PRIMARY_PLANE;
133    return true;
134}
135
136void TngPrimaryPlane::setZOrderConfig(ZOrderConfig& zorderConfig,
137                                           void *nativeConfig)
138{
139    if (!nativeConfig) {
140        ETRACE("Invalid parameter, no native config");
141        return;
142    }
143
144    mForceBottom = false;
145
146    int primaryIndex = -1;
147    int overlayIndex = -1;
148    // only consider force bottom when overlay is active
149    for (size_t i = 0; i < zorderConfig.size(); i++) {
150        DisplayPlane *plane = zorderConfig[i]->plane;
151        if (plane->getType() == DisplayPlane::PLANE_PRIMARY)
152            primaryIndex = i;
153        if (plane->getType() == DisplayPlane::PLANE_OVERLAY) {
154            overlayIndex = i;
155        }
156    }
157
158    // if has overlay plane which is below primary plane
159    if (overlayIndex > primaryIndex) {
160        mForceBottom = true;
161    }
162
163    struct intel_dc_plane_zorder *zorder =
164        (struct intel_dc_plane_zorder *)nativeConfig;
165    zorder->forceBottom[mIndex] = mForceBottom ? 1 : 0;
166}
167
168bool TngPrimaryPlane::assignToDevice(int disp)
169{
170    DisplayPlane::assignToDevice(disp);
171    return true;
172}
173
174} // namespace intel
175} // namespace android
176