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 <Hwcomposer.h>
18#include <BufferManager.h>
19#include <tangier/TngSpritePlane.h>
20#include <common/PixelFormat.h>
21
22namespace android {
23namespace intel {
24
25TngSpritePlane::TngSpritePlane(int index, int disp)
26    : SpritePlaneBase(index, disp)
27{
28    CTRACE();
29    memset(&mContext, 0, sizeof(mContext));
30}
31
32TngSpritePlane::~TngSpritePlane()
33{
34    CTRACE();
35}
36
37bool TngSpritePlane::setDataBuffer(BufferMapper& mapper)
38{
39    int bpp;
40    int srcX, srcY;
41    int dstX, dstY, dstW, dstH;
42    uint32_t spriteFormat;
43    uint32_t stride;
44    uint32_t linoff;
45    uint32_t planeAlpha;
46
47    CTRACE();
48
49    // setup plane position
50    dstX = mPosition.x;
51    dstY = mPosition.y;
52    dstW = mPosition.w;
53    dstH = mPosition.h;
54
55    checkPosition(dstX, dstY, dstW, dstH);
56
57    // setup plane format
58    if (!PixelFormat::convertFormat(mapper.getFormat(), spriteFormat, bpp)) {
59        ETRACE("unsupported format %#x", mapper.getFormat());
60        return false;
61    }
62
63    // setup stride and source buffer crop
64    srcX = mapper.getCrop().x;
65    srcY = mapper.getCrop().y;
66    stride = mapper.getStride().rgb.stride;
67#ifdef ENABLE_ROTATION_180
68    linoff = (mapper.getCrop().h + srcY - 1) * stride + (srcX + mapper.getCrop().w - 1) * bpp;
69#else
70    linoff = srcY * stride + srcX * bpp;
71#endif
72
73    // setup plane alpha
74    if ((mBlending == HWC_BLENDING_PREMULT) && (mPlaneAlpha == 0)) {
75       planeAlpha = mPlaneAlpha | 0x80000000;
76    } else {
77       // disable plane alpha to offload HW
78       planeAlpha = 0;
79    }
80
81    // unlikely happen, but still we need make sure linoff is valid
82    if (linoff > (stride * mapper.getHeight())) {
83        ETRACE("invalid source crop");
84        return false;
85    }
86
87    // update context
88    mContext.type = DC_SPRITE_PLANE;
89    mContext.ctx.sp_ctx.index = mIndex;
90    mContext.ctx.sp_ctx.pipe = mDevice;
91    // none blending and BRGA format layer,set format to BGRX8888
92    if (mBlending == HWC_BLENDING_NONE && spriteFormat == PixelFormat::PLANE_PIXEL_FORMAT_BGRA8888)
93	mContext.ctx.sp_ctx.cntr = PixelFormat::PLANE_PIXEL_FORMAT_BGRX8888
94					| 0x80000000;
95    else
96	mContext.ctx.sp_ctx.cntr = spriteFormat | 0x80000000;
97    mContext.ctx.sp_ctx.linoff = linoff;
98    mContext.ctx.sp_ctx.stride = stride;
99    mContext.ctx.sp_ctx.surf = mapper.getGttOffsetInPage(0) << 12;
100    mContext.ctx.sp_ctx.pos = (dstY & 0xfff) << 16 | (dstX & 0xfff);
101    mContext.ctx.sp_ctx.size =
102        ((dstH - 1) & 0xfff) << 16 | ((dstW - 1) & 0xfff);
103    mContext.ctx.sp_ctx.contalpa = planeAlpha;
104    mContext.ctx.sp_ctx.update_mask = SPRITE_UPDATE_ALL;
105    mContext.gtt_key = (uint64_t)mapper.getCpuAddress(0);
106#ifdef ENABLE_ROTATION_180
107    mContext.ctx.sp_ctx.cntr |= 1 << 15;
108#endif
109    VTRACE("cntr = %#x, linoff = %#x, stride = %#x,"
110          "surf = %#x, pos = %#x, size = %#x, contalpa = %#x",
111          mContext.ctx.sp_ctx.cntr,
112          mContext.ctx.sp_ctx.linoff,
113          mContext.ctx.sp_ctx.stride,
114          mContext.ctx.sp_ctx.surf,
115          mContext.ctx.sp_ctx.pos,
116          mContext.ctx.sp_ctx.size,
117          mContext.ctx.sp_ctx.contalpa);
118    return true;
119}
120
121void* TngSpritePlane::getContext() const
122{
123    CTRACE();
124    return (void *)&mContext;
125}
126
127bool TngSpritePlane::enablePlane(bool enabled)
128{
129    RETURN_FALSE_IF_NOT_INIT();
130
131    struct drm_psb_register_rw_arg arg;
132    memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
133    if (enabled) {
134        arg.plane_enable_mask = 1;
135    } else {
136        arg.plane_disable_mask = 1;
137    }
138    arg.plane.type = DC_SPRITE_PLANE;
139    arg.plane.index = mIndex;
140    arg.plane.ctx = 0;
141
142    // issue ioctl
143    Drm *drm = Hwcomposer::getInstance().getDrm();
144    bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
145    if (ret == false) {
146        WTRACE("sprite enabling (%d) failed with error code %d", enabled, ret);
147        return false;
148    }
149
150    Hwcomposer& hwc = Hwcomposer::getInstance();
151    DisplayPlaneManager *pm = hwc.getPlaneManager();
152    void *config = pm->getZOrderConfig();
153    if (config != NULL) {
154        struct intel_dc_plane_zorder *zorder =  (struct intel_dc_plane_zorder *)config;
155        zorder->abovePrimary = 0;
156    }
157
158    return true;
159
160}
161
162bool TngSpritePlane::isDisabled()
163{
164    RETURN_FALSE_IF_NOT_INIT();
165
166    struct drm_psb_register_rw_arg arg;
167    memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
168
169    if (mType == DisplayPlane::PLANE_SPRITE)
170        arg.plane.type = DC_SPRITE_PLANE;
171    else
172        arg.plane.type = DC_PRIMARY_PLANE;
173
174    arg.get_plane_state_mask = 1;
175    arg.plane.index = mIndex;
176    arg.plane.ctx = 0;
177
178    // issue ioctl
179    Drm *drm = Hwcomposer::getInstance().getDrm();
180    bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
181    if (ret == false) {
182        WTRACE("plane state query failed with error code %d", ret);
183        return false;
184    }
185
186    return arg.plane.ctx == PSB_DC_PLANE_DISABLED;
187}
188
189void TngSpritePlane::setZOrderConfig(ZOrderConfig& zorderConfig,
190                                          void *nativeConfig)
191{
192    if (!nativeConfig) {
193        ETRACE("Invalid parameter, no native config");
194        return;
195    }
196
197    mAbovePrimary = false;
198
199    int primaryIndex = -1;
200    int spriteIndex = -1;
201    // only consider force bottom when overlay is active
202    for (size_t i = 0; i < zorderConfig.size(); i++) {
203        DisplayPlane *plane = zorderConfig[i]->plane;
204        if (plane->getType() == DisplayPlane::PLANE_PRIMARY)
205            primaryIndex = i;
206        if (plane->getType() == DisplayPlane::PLANE_SPRITE) {
207            spriteIndex = i;
208        }
209    }
210
211    // if has overlay plane which is below primary plane
212    if (spriteIndex > primaryIndex) {
213        mAbovePrimary = true;
214    }
215
216    struct intel_dc_plane_zorder *zorder =
217        (struct intel_dc_plane_zorder *)nativeConfig;
218    zorder->abovePrimary = mAbovePrimary ? 1 : 0;
219}
220} // namespace intel
221} // namespace android
222