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 <utils/String8.h>
18 #include <anniedale/AnnPlaneManager.h>
19 #include <anniedale/AnnRGBPlane.h>
20 #include <anniedale/AnnOverlayPlane.h>
21 #include <anniedale/AnnCursorPlane.h>
22 #include <PlaneCapabilities.h>
23 
24 namespace android {
25 namespace intel {
26 
27 
28 struct PlaneDescription {
29     char nickname;
30     int type;
31     int index;
32 };
33 
34 
35 static PlaneDescription PLANE_DESC[] =
36 {
37     // nickname must be continous and start with 'A',
38     // it is used to fast locate plane index and type
39     {'A', DisplayPlane::PLANE_PRIMARY, 0},
40     {'B', DisplayPlane::PLANE_PRIMARY, 1},
41     {'C', DisplayPlane::PLANE_PRIMARY, 2},
42     {'D', DisplayPlane::PLANE_SPRITE,  0},
43     {'E', DisplayPlane::PLANE_SPRITE,  1},
44     {'F', DisplayPlane::PLANE_SPRITE,  2},
45     {'G', DisplayPlane::PLANE_OVERLAY, 0},  // nickname for Overlay A
46     {'H', DisplayPlane::PLANE_OVERLAY, 1},   // nickname for Overlay C
47     {'I', DisplayPlane::PLANE_CURSOR,  0},  // nickname for cursor A
48     {'J', DisplayPlane::PLANE_CURSOR,  1},  // nickname for cursor B
49     {'K', DisplayPlane::PLANE_CURSOR,  2}   // nickname for cursor C
50 };
51 
52 
53 struct ZOrderDescription {
54     int index;  // based on overlay position
55     const char *zorder;
56 };
57 
58 // If overlay is in the bottom of Z order, two legitimate combinations are Oa, D, E, F
59 // and Oc, D, E, F. However, plane A has to be part of the blending chain as it can't
60 //  be disabled [HW bug]. The only legitimate combinations including overlay and plane A is:
61 // A, Oa, E, F
62 // A, Oc, E, F
63 // Cursor plane can be placed on top of any plane below and is intentionally ignored
64 // in the zorder table.
65 
66 // video mode panel doesn't need the primay plane A always on hack
67 static ZOrderDescription PIPE_A_ZORDER_DESC_VID[] =
68 {
69     {0, "ADEF"},  // no overlay
70     {1, "GDEF"},  // overlay A at bottom (1 << 0)
71     {1, "HDEF"},  // overlay C at bottom (1 << 0)
72     {2, "AGEF"},  // overlay A at next to bottom (1 << 1)
73     {2, "AHEF"},  // overlay C at next to bottom (1 << 1)
74     {3, "GHEF"},  // overlay A, C at bottom
75     {4, "ADGF"},  // overlay A at next to top (1 << 2)
76     {4, "ADHF"},  // overlay C at next to top (1 << 2)
77     {6, "AGHF"},  // overlay A, C in between
78     {8, "ADEG"},  // overlay A at top (1 << 3)
79     {8, "ADEH"},  // overlay C at top (1 <<3)
80     {12, "ADGH"}  // overlay A, C at top
81 };
82 
83 static ZOrderDescription PIPE_A_ZORDER_DESC_CMD[] =
84 {
85     {0, "ADEF"},  // no overlay
86     {1, "GEF"},  // overlay A at bottom (1 << 0)
87     {1, "HEF"},  // overlay C at bottom (1 << 0)
88     {2, "AGEF"},  // overlay A at next to bottom (1 << 1)
89     {2, "AHEF"},  // overlay C at next to bottom (1 << 1)
90     {3, "GHF"},   // overlay A, C at bottom
91     {4, "ADGF"},  // overlay A at next to top (1 << 2)
92     {4, "ADHF"},  // overlay C at next to top (1 << 2)
93     {6, "AGHF"},  // overlay A, C in between
94     {8, "ADEG"},  // overlay A at top (1 << 3)
95     {8, "ADEH"},  // overlay C at top (1 <<3)
96     {12, "ADGH"}  // overlay A, C at top
97 };
98 
99 // use overlay C over overlay A if possible on pipe B
100 static ZOrderDescription PIPE_B_ZORDER_DESC[] =
101 {
102     {0, "BD"},    // no overlay
103     {1, "HBD"},   // overlay C at bottom (1 << 0)
104 //    {1, "GBD"},   // overlay A at bottom (1 << 0), overlay A don`t switch to pipeB and only overlay C on pipeB
105     {2, "BHD"},   // overlay C at middle (1 << 1)
106 //   {2, "BGD"},   // overlay A at middle (1 << 1), overlay A don`t switch to pipeB and only overaly C on pipeB
107     {3, "GHBD"},  // overlay A and C at bottom ( 1 << 0 + 1 << 1)
108     {4, "BDH"},   // overlay C at top (1 << 2)
109     {4, "BDG"},   // overlay A at top (1 << 2)
110     {6, "BGHD"},  // overlay A/C at middle  1 << 1 + 1 << 2)
111     {12, "BDGH"}  // overlay A/C at top (1 << 2 + 1 << 3)
112 };
113 
114 static ZOrderDescription *PIPE_A_ZORDER_TBL;
115 static int PIPE_A_ZORDER_COMBINATIONS;
116 static ZOrderDescription *PIPE_B_ZORDER_TBL;
117 static int PIPE_B_ZORDER_COMBINATIONS;
118 static bool OVERLAY_HW_WORKAROUND;
119 
AnnPlaneManager()120 AnnPlaneManager::AnnPlaneManager()
121     : DisplayPlaneManager()
122 {
123 }
124 
~AnnPlaneManager()125 AnnPlaneManager::~AnnPlaneManager()
126 {
127 }
128 
initialize()129 bool AnnPlaneManager::initialize()
130 {
131     mSpritePlaneCount = 3;  // Sprite D, E, F
132     mOverlayPlaneCount = 2; // Overlay A, C
133     mPrimaryPlaneCount = 3; // Primary A, B, C
134     mCursorPlaneCount = 3;
135 
136     uint32_t videoMode = 0;
137     Drm *drm = Hwcomposer::getInstance().getDrm();
138     drm->readIoctl(DRM_PSB_PANEL_QUERY, &videoMode, sizeof(uint32_t));
139     if (videoMode == 1) {
140         DTRACE("video mode panel, no primay A always on hack");
141         PIPE_A_ZORDER_TBL = PIPE_A_ZORDER_DESC_VID;
142         PIPE_A_ZORDER_COMBINATIONS =
143             sizeof(PIPE_A_ZORDER_DESC_VID)/sizeof(ZOrderDescription);
144     } else {
145         DTRACE("command mode panel, need primay A always on hack");
146         PIPE_A_ZORDER_TBL = PIPE_A_ZORDER_DESC_CMD;
147         PIPE_A_ZORDER_COMBINATIONS =
148             sizeof(PIPE_A_ZORDER_DESC_CMD)/sizeof(ZOrderDescription);
149 	OVERLAY_HW_WORKAROUND = true;
150     }
151 
152     PIPE_B_ZORDER_TBL = PIPE_B_ZORDER_DESC;
153     PIPE_B_ZORDER_COMBINATIONS =
154         sizeof(PIPE_B_ZORDER_DESC)/sizeof(ZOrderDescription);
155 
156     return DisplayPlaneManager::initialize();
157 }
158 
deinitialize()159 void AnnPlaneManager::deinitialize()
160 {
161     DisplayPlaneManager::deinitialize();
162 }
163 
allocPlane(int index,int type)164 DisplayPlane* AnnPlaneManager::allocPlane(int index, int type)
165 {
166     DisplayPlane *plane = NULL;
167 
168     switch (type) {
169     case DisplayPlane::PLANE_PRIMARY:
170         plane = new AnnRGBPlane(index, DisplayPlane::PLANE_PRIMARY, index/*disp*/);
171         break;
172     case DisplayPlane::PLANE_SPRITE:
173         plane = new AnnRGBPlane(index, DisplayPlane::PLANE_SPRITE, 0/*disp*/);
174         break;
175     case DisplayPlane::PLANE_OVERLAY:
176         plane = new AnnOverlayPlane(index, 0/*disp*/);
177         break;
178     case DisplayPlane::PLANE_CURSOR:
179         plane = new AnnCursorPlane(index, index /*disp */);
180         break;
181     default:
182         ETRACE("unsupported type %d", type);
183         break;
184     }
185 
186     if (plane && !plane->initialize(DisplayPlane::MIN_DATA_BUFFER_COUNT)) {
187         ETRACE("failed to initialize plane.");
188         DEINIT_AND_DELETE_OBJ(plane);
189     }
190 
191     return plane;
192 }
193 
isValidZOrder(int dsp,ZOrderConfig & config)194 bool AnnPlaneManager::isValidZOrder(int dsp, ZOrderConfig& config)
195 {
196     int size = (int)config.size();
197     bool hasCursor = false;
198 
199     for (int i = 0; i < size; i++) {
200         if (config[i]->planeType == DisplayPlane::PLANE_CURSOR) {
201             hasCursor = true;
202             break;
203         }
204     }
205 
206     if (size <= 0 ||
207         (hasCursor && size > 5) ||
208         (!hasCursor && size > 4)) {
209         VTRACE("invalid z order config size %d", size);
210         return false;
211     }
212 
213     if (dsp == IDisplayDevice::DEVICE_PRIMARY) {
214         int firstOverlay = -1;
215         for (int i = 0; i < size; i++) {
216             if (config[i]->planeType == DisplayPlane::PLANE_OVERLAY) {
217                 firstOverlay = i;
218                 break;
219             }
220         }
221 
222         int sprites = 0;
223         for (int i = 0; i < size; i++) {
224             if (config[i]->planeType != DisplayPlane::PLANE_OVERLAY &&
225                 config[i]->planeType != DisplayPlane::PLANE_CURSOR) {
226                 sprites++;
227             }
228         }
229 
230         if (firstOverlay < 0 && sprites > 4) {
231             VTRACE("not capable to support more than 4 sprite layers");
232             return false;
233         }
234 
235         if (OVERLAY_HW_WORKAROUND) {
236             if (firstOverlay == 0 && size > 2) {
237                 VTRACE("can not support 3 sprite layers on top of overlay");
238                 return false;
239             }
240         }
241     } else if (dsp == IDisplayDevice::DEVICE_EXTERNAL) {
242         int sprites = 0;
243         for (int i = 0; i < size; i++) {
244             if (config[i]->planeType != DisplayPlane::PLANE_OVERLAY &&
245                 config[i]->planeType != DisplayPlane::PLANE_CURSOR) {
246                 sprites++;
247             }
248         }
249         if (sprites > 2) {
250             ETRACE("number of sprite: %d, maximum 1 sprite and 1 primary supported on pipe 1", sprites);
251             return false;
252         }
253     } else {
254         ETRACE("invalid display device %d", dsp);
255         return false;
256     }
257     return true;
258 }
259 
assignPlanes(int dsp,ZOrderConfig & config)260 bool AnnPlaneManager::assignPlanes(int dsp, ZOrderConfig& config)
261 {
262     if (dsp < 0 || dsp > IDisplayDevice::DEVICE_EXTERNAL) {
263         ETRACE("invalid display device %d", dsp);
264         return false;
265     }
266 
267     int size = (int)config.size();
268 
269     // calculate index based on overlay Z order position
270     int index = 0;
271     for (int i = 0; i < size; i++) {
272         if (config[i]->planeType == DisplayPlane::PLANE_OVERLAY) {
273             index += (1 << i);
274         }
275     }
276 
277     int combinations;
278     ZOrderDescription *table;
279     if (dsp == IDisplayDevice::DEVICE_PRIMARY) {
280         combinations = PIPE_A_ZORDER_COMBINATIONS;
281         table = PIPE_A_ZORDER_TBL;
282     } else {
283         combinations = PIPE_B_ZORDER_COMBINATIONS;
284         table = PIPE_B_ZORDER_TBL;
285     }
286 
287     for (int i = 0; i < combinations; i++) {
288         ZOrderDescription *zorderDesc = table + i;
289 
290         if (zorderDesc->index != index)
291             continue;
292 
293         if (assignPlanes(dsp, config, zorderDesc->zorder)) {
294             VTRACE("zorder assigned %s", zorderDesc->zorder);
295             return true;
296         }
297     }
298     return false;
299 }
300 
assignPlanes(int dsp,ZOrderConfig & config,const char * zorder)301 bool AnnPlaneManager::assignPlanes(int dsp, ZOrderConfig& config, const char *zorder)
302 {
303     // zorder string does not include cursor plane, therefore cursor layer needs to be handled
304     // in a special way. Cursor layer must be on top of zorder and no more than one cursor layer.
305 
306     int size = (int)config.size();
307     if (zorder == NULL || size == 0) {
308         //DTRACE("invalid zorder or ZOrder config.");
309         return false;
310     }
311 
312     int zorderLen = (int)strlen(zorder);
313 
314     // test if plane is avalable
315     for (int i = 0; i < size; i++) {
316         if (config[i]->planeType == DisplayPlane::PLANE_CURSOR) {
317             if (i != size - 1) {
318                 ETRACE("invalid zorder of cursor layer");
319                 return false;
320             }
321             PlaneDescription& desc = PLANE_DESC['I' - 'A' + dsp];
322             if (!isFreePlane(desc.type, desc.index)) {
323                 ETRACE("cursor plane is not available");
324                 return false;
325             }
326             continue;
327         }
328         if (i >= zorderLen) {
329             DTRACE("index of ZOrderConfig is out of bound");
330             return false;
331         }
332 
333         char id = *(zorder + i);
334         PlaneDescription& desc = PLANE_DESC[id - 'A'];
335         if (!isFreePlane(desc.type, desc.index)) {
336             DTRACE("plane type %d index %d is not available", desc.type, desc.index);
337             return false;
338         }
339 
340 #if 0
341         // plane type check
342         if (config[i]->planeType == DisplayPlane::PLANE_OVERLAY &&
343             desc.type != DisplayPlane::PLANE_OVERLAY) {
344             ETRACE("invalid plane type %d, expected %d", desc.type, config[i]->planeType);
345             return false;
346         }
347 
348         if (config[i]->planeType != DisplayPlane::PLANE_OVERLAY) {
349             if (config[i]->planeType != DisplayPlane::PLANE_PRIMARY &&
350                 config[i]->planeType != DisplayPlane::PLANE_SPRITE) {
351                 ETRACE("invalid plane type %d,", config[i]->planeType);
352                 return false;
353             }
354             if (desc.type != DisplayPlane::PLANE_PRIMARY &&
355                 desc.type != DisplayPlane::PLANE_SPRITE) {
356                 ETRACE("invalid plane type %d, expected %d", desc.type, config[i]->planeType);
357                 return false;
358             }
359         }
360 #endif
361 
362         if  (desc.type == DisplayPlane::PLANE_OVERLAY && desc.index == 1 &&
363              config[i]->hwcLayer->getTransform() != 0) {
364             DTRACE("overlay C does not support transform");
365             return false;
366         }
367     }
368 
369     bool primaryPlaneActive = false;
370     // allocate planes
371     for (int i = 0; i < size; i++) {
372         if (config[i]->planeType == DisplayPlane::PLANE_CURSOR) {
373             PlaneDescription& desc = PLANE_DESC['I' - 'A' + dsp];
374             ZOrderLayer *zLayer = config.itemAt(i);
375             zLayer->plane = getPlane(desc.type, desc.index);
376             if (zLayer->plane == NULL) {
377                 ETRACE("failed to get cursor plane, should never happen!");
378             }
379             continue;
380         }
381 
382         char id = *(zorder + i);
383         PlaneDescription& desc = PLANE_DESC[id - 'A'];
384         ZOrderLayer *zLayer = config.itemAt(i);
385         zLayer->plane = getPlane(desc.type, desc.index);
386         if (zLayer->plane == NULL) {
387             ETRACE("failed to get plane, should never happen!");
388         }
389         // override type
390         zLayer->planeType = desc.type;
391         if (desc.type == DisplayPlane::PLANE_PRIMARY) {
392             primaryPlaneActive = true;
393         }
394     }
395 
396     // setup Z order
397     int slot = 0;
398     for (int i = 0; i < size; i++) {
399         slot = i;
400 
401         if (OVERLAY_HW_WORKAROUND) {
402             if (!primaryPlaneActive &&
403                 config[i]->planeType == DisplayPlane::PLANE_OVERLAY) {
404                 slot += 1;
405             }
406         }
407 
408         config[i]->plane->setZOrderConfig(config, (void *)(unsigned long)slot);
409         config[i]->plane->enable();
410     }
411 
412 #if 0
413     DTRACE("config size %d, zorder %s", size, zorder);
414     for (int i = 0; i < size; i++) {
415         const ZOrderLayer *l = config.itemAt(i);
416         ITRACE("%d: plane type %d, index %d, zorder %d",
417             i, l->planeType, l->plane->getIndex(), l->zorder);
418     }
419 #endif
420 
421     return true;
422 }
423 
getZOrderConfig() const424 void* AnnPlaneManager::getZOrderConfig() const
425 {
426     return NULL;
427 }
428 
getFreePlanes(int dsp,int type)429 int AnnPlaneManager::getFreePlanes(int dsp, int type)
430 {
431     RETURN_NULL_IF_NOT_INIT();
432 
433     if (type != DisplayPlane::PLANE_SPRITE) {
434         return DisplayPlaneManager::getFreePlanes(dsp, type);
435     }
436 
437     if (dsp < 0 || dsp > IDisplayDevice::DEVICE_EXTERNAL) {
438         ETRACE("invalid display device %d", dsp);
439         return 0;
440     }
441 
442     uint32_t freePlanes = mFreePlanes[type] | mReclaimedPlanes[type];
443     int start = 0;
444     int stop = mSpritePlaneCount;
445     if (dsp == IDisplayDevice::DEVICE_EXTERNAL) {
446         // only Sprite D (index 0) can be assigned to pipe 1
447         // Sprites E/F (index 1, 2) are fixed on pipe 0
448         stop = 1;
449     }
450     int count = 0;
451     for (int i = start; i < stop; i++) {
452         if ((1 << i) & freePlanes) {
453             count++;
454         }
455     }
456     return count;
457 }
458 
459 } // namespace intel
460 } // namespace android
461 
462