1 /*
2 * Copyright (C) 2022 The Android Open Source Project
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
17 #include "ExynosResourceManagerModule.h"
18
19 #include <cutils/properties.h>
20
21 #include <list>
22 #include <utility>
23
24 #include "ExynosLayer.h"
25
26 using namespace zuma;
27
28 constexpr uint32_t TDM_OVERLAP_MARGIN = 68;
29
30 constexpr uint32_t kSramSBWCWidthAlign = 32;
31 constexpr uint32_t kSramSBWCWidthMargin = kSramSBWCWidthAlign - 1;
32 constexpr uint32_t kSramSBWCRotWidthAlign = 4;
33 constexpr uint32_t kSramAFBC8B4BAlign = 8;
34 constexpr uint32_t kSramAFBC8B4BMargin = kSramAFBC8B4BAlign - 1;
35 constexpr uint32_t kSramAFBC2BAlign = 16;
36 constexpr uint32_t kSramAFBC2BMargin = kSramAFBC2BAlign - 1;
37
ExynosResourceManagerModule(ExynosDevice * device)38 ExynosResourceManagerModule::ExynosResourceManagerModule(ExynosDevice *device)
39 : gs201::ExynosResourceManagerModule(device)
40 {
41 // HW Resource Table for TDM based allocation
42 mHWResourceTables = &HWResourceTables;
43
44 char value[PROPERTY_VALUE_MAX];
45 property_get("ro.boot.hw.soc.rev", value, "2");
46 const int socRev = atoi(value);
47 mConstraintRev = socRev < 2 ? CONSTRAINT_A0 : CONSTRAINT_B0;
48 HWAttrs.at(TDM_ATTR_WCG).loadSharing =
49 (mConstraintRev == CONSTRAINT_A0) ? LS_DPUF : LS_DPUF_AXI;
50 ALOGD("%s(): ro.boot.hw.soc.rev=%s ConstraintRev=%d", __func__, value, mConstraintRev);
51 }
52
~ExynosResourceManagerModule()53 ExynosResourceManagerModule::~ExynosResourceManagerModule() {}
54
checkTDMResource(ExynosDisplay * display,ExynosMPP * currentMPP,ExynosMPPSource * mppSrc)55 bool ExynosResourceManagerModule::checkTDMResource(ExynosDisplay *display, ExynosMPP *currentMPP,
56 ExynosMPPSource *mppSrc) {
57 std::array<uint32_t, TDM_ATTR_MAX> accumulatedDPUFAmount{};
58 std::array<uint32_t, TDM_ATTR_MAX> accumulatedDPUFAXIAmount{};
59 const uint32_t blkId = currentMPP->getHWBlockId();
60 const uint32_t axiId = currentMPP->getAXIPortId();
61 HDEBUGLOGD(eDebugTDM, "%s : %p trying to assign to %s, compare with layers", __func__,
62 mppSrc->mSrcImg.bufferHandle, currentMPP->mName.string());
63 ExynosLayer *layer = (mppSrc->mSourceType == MPP_SOURCE_LAYER) ? (ExynosLayer *)mppSrc : nullptr;
64
65 for (auto compLayer : display->mLayers) {
66 ExynosMPP *otfMPP = compLayer->mOtfMPP;
67 if (!otfMPP || layer == compLayer) continue;
68 getAmounts(display, blkId, axiId, otfMPP, mppSrc, compLayer,
69 accumulatedDPUFAmount, accumulatedDPUFAXIAmount);
70 }
71
72 if (display->mExynosCompositionInfo.mHasCompositionLayer) {
73 HDEBUGLOGD(eDebugTDM,
74 "%s : %p trying to assign to %s, compare with ExynosComposition Target buffer",
75 __func__, mppSrc->mSrcImg.bufferHandle, currentMPP->mName.string());
76 ExynosMPP *otfMPP = display->mExynosCompositionInfo.mOtfMPP;
77 if (otfMPP)
78 getAmounts(display, blkId, axiId, otfMPP, mppSrc, &display->mExynosCompositionInfo,
79 accumulatedDPUFAmount, accumulatedDPUFAXIAmount);
80 }
81
82 if (display->mClientCompositionInfo.mHasCompositionLayer) {
83 HDEBUGLOGD(eDebugTDM,
84 "%s : %p trying to assign to %s, compare with ClientComposition Target buffer",
85 __func__, mppSrc->mSrcImg.bufferHandle, currentMPP->mName.string());
86 ExynosMPP *otfMPP = display->mClientCompositionInfo.mOtfMPP;
87 if (otfMPP)
88 getAmounts(display, blkId, axiId, otfMPP, mppSrc, &display->mClientCompositionInfo,
89 accumulatedDPUFAmount, accumulatedDPUFAXIAmount);
90 }
91
92 for (auto attr = HWAttrs.begin(); attr != HWAttrs.end(); attr++) {
93 const LoadSharing_t &loadSharing = attr->second.loadSharing;
94 uint32_t currentAmount = mppSrc->getHWResourceAmount(attr->first);
95 auto &accumulatedAmount =
96 (loadSharing == LS_DPUF) ? accumulatedDPUFAmount : accumulatedDPUFAXIAmount;
97 const auto &TDMInfoIdx =
98 std::make_pair(blkId,
99 (loadSharing == LS_DPUF) ? AXI_DONT_CARE : axiId);
100 int32_t totalAmount =
101 display->mDisplayTDMInfo[TDMInfoIdx].getAvailableAmount(attr->first).totalAmount;
102 HDEBUGLOGD(eDebugTDM,
103 "%s, layer[%p] -> %s attr[%s],ls=%d,accumulated:%d,current:%d,total: %d",
104 __func__, mppSrc->mSrcImg.bufferHandle, currentMPP->mName.string(),
105 attr->second.name.string(), loadSharing, accumulatedAmount[attr->first],
106 currentAmount, totalAmount);
107 if (accumulatedAmount[attr->first] + currentAmount > totalAmount) {
108 HDEBUGLOGD(eDebugTDM, "%s, %s could not assigned by attr[%s]", __func__,
109 currentMPP->mName.string(), attr->second.name.string());
110 return false;
111 }
112 }
113
114 HDEBUGLOGD(eDebugTDM, "%s : %p trying to assign to %s successfully", __func__,
115 mppSrc->mSrcImg.bufferHandle, currentMPP->mName.string());
116 return true;
117 }
118
isHWResourceAvailable(ExynosDisplay * display,ExynosMPP * currentMPP,ExynosMPPSource * mppSrc)119 bool ExynosResourceManagerModule::isHWResourceAvailable(ExynosDisplay *display,
120 ExynosMPP *currentMPP,
121 ExynosMPPSource *mppSrc) {
122 if (!checkTDMResource(display, currentMPP, mppSrc)) {
123 return false;
124 }
125
126 std::list<ExynosLayer *> overlappedLayers;
127 uint32_t currentBlockId = currentMPP->getHWBlockId();
128 for (auto layer : display->mLayers) {
129 ExynosMPP *otfMPP = layer->mOtfMPP;
130 if (!otfMPP || dynamic_cast<ExynosMPPSource *>(layer) == mppSrc) continue;
131
132 if ((currentBlockId == otfMPP->getHWBlockId()) && isOverlapped(display, mppSrc, layer))
133 overlappedLayers.push_back(layer);
134 }
135
136 if (overlappedLayers.size()) {
137 HDEBUGLOGD(eDebugTDM,
138 "%s : %p trying to assign to %s, check its overlapped layers(%zu) status",
139 __func__, mppSrc->mSrcImg.bufferHandle, currentMPP->mName.string(),
140 overlappedLayers.size());
141
142 for (auto &overlappedLayer : overlappedLayers) {
143 HDEBUGLOGD(eDebugTDM, "%s : %p overlapped %p", __func__, mppSrc->mSrcImg.bufferHandle,
144 overlappedLayer->mLayerBuffer);
145 if (!checkTDMResource(display, overlappedLayer->mOtfMPP, overlappedLayer)) {
146 return false;
147 }
148 }
149 }
150 return true;
151 }
152
setupHWResource(const tdm_attr_t & tdmAttrId,const String8 & name,const DPUblockId_t & blkId,const AXIPortId_t & axiId,ExynosDisplay * display,ExynosDisplay * addedDisplay,const ConstraintRev_t & constraintsRev)153 void ExynosResourceManagerModule::setupHWResource(const tdm_attr_t &tdmAttrId, const String8 &name,
154 const DPUblockId_t &blkId,
155 const AXIPortId_t &axiId, ExynosDisplay *display,
156 ExynosDisplay *addedDisplay,
157 const ConstraintRev_t &constraintsRev) {
158 const int32_t dispType = display->mType;
159 const auto &resourceIdx = HWResourceIndexes(tdmAttrId, blkId, axiId, dispType, constraintsRev);
160 const auto &iter = mHWResourceTables->find(resourceIdx);
161 if (iter != mHWResourceTables->end()) {
162 auto &hwResource = iter->second;
163 const auto &TDMInfoIdx = (HWAttrs.at(tdmAttrId).loadSharing == LS_DPUF)
164 ? std::make_pair(blkId, AXI_DONT_CARE)
165 : std::make_pair(blkId, axiId);
166 uint32_t amount = (addedDisplay == nullptr) ? hwResource.maxAssignedAmount
167 : hwResource.totalAmount -
168 addedDisplay->mDisplayTDMInfo[TDMInfoIdx]
169 .getAvailableAmount(tdmAttrId)
170 .totalAmount;
171 display->mDisplayTDMInfo[TDMInfoIdx].initTDMInfo(DisplayTDMInfo::ResourceAmount_t{amount},
172 tdmAttrId);
173 if (addedDisplay == nullptr) {
174 HDEBUGLOGD(eDebugTDM, "(%s=>%s) : %s amount is updated to %d",
175 resourceIdx.toString8().string(), iter->first.toString8().string(),
176 name.string(), amount);
177 } else {
178 HDEBUGLOGD(eDebugTDM,
179 "(%s=>%s) : hwResource.totalAmount=%d %s amount is updated to %d",
180 resourceIdx.toString8().string(), iter->first.toString8().string(),
181 hwResource.totalAmount, name.string(), amount);
182 }
183 } else {
184 ALOGW("(%s): cannot find resource for %s", resourceIdx.toString8().string(), name.string());
185 }
186 }
187
setDisplaysTDMInfo()188 uint32_t ExynosResourceManagerModule::setDisplaysTDMInfo()
189 {
190 ExynosDisplay *addedDisplay = nullptr;
191
192 /*
193 * Checking display connections,
194 * Assume that WFD and External are not connected at the same time
195 * If non-primary display is connected, primary display's HW resource is looted
196 */
197 for (auto &display : mDisplays) {
198 if (display->mType == HWC_DISPLAY_PRIMARY) continue;
199 if (display->isEnabled()) {
200 addedDisplay = display;
201 break;
202 }
203 }
204
205 /*
206 * Update Primary's resource amount. primary = total - loot(other display's HW resource)
207 * Other's aready defined at initDisplaysTDMInfo()
208 */
209 ExynosDisplay *primaryDisplay = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
210 for (auto attr = HWAttrs.begin(); attr != HWAttrs.end(); attr++) {
211 for (auto blockId = DPUBlocks.begin(); blockId != DPUBlocks.end(); blockId++) {
212 if (attr->second.loadSharing == LS_DPUF) {
213 setupHWResource(attr->first, attr->second.name, blockId->first, AXI_DONT_CARE,
214 primaryDisplay, addedDisplay, mConstraintRev);
215 } else if (attr->second.loadSharing == LS_DPUF_AXI) {
216 for (auto axi = AXIPorts.begin(); axi != AXIPorts.end(); ++axi) {
217 setupHWResource(attr->first, attr->second.name, blockId->first, axi->first,
218 primaryDisplay, addedDisplay, mConstraintRev);
219 }
220 }
221 }
222 }
223
224 if (hwcCheckDebugMessages(eDebugTDM)) {
225 for (auto &display : mDisplays) {
226 for (auto attr = HWAttrs.begin(); attr != HWAttrs.end(); attr++) {
227 for (auto blockId = DPUBlocks.begin(); blockId != DPUBlocks.end(); blockId++) {
228 if (attr->second.loadSharing == LS_DPUF) {
229 const auto &TDMInfoId = std::make_pair(blockId->first, AXI_DONT_CARE);
230 int32_t amount = display->mDisplayTDMInfo[TDMInfoId]
231 .getAvailableAmount(attr->first)
232 .totalAmount;
233 HDEBUGLOGD(eDebugTDM, "%s : [%s] display:%d,block:%d, amount : %d(%s)",
234 __func__, attr->second.name.string(), display->mType,
235 blockId->first, amount,
236 display->isEnabled() ? "used" : "not used");
237 } else {
238 for (auto axi = AXIPorts.begin(); axi != AXIPorts.end(); ++axi) {
239 const auto &TDMInfoId = std::make_pair(blockId->first, axi->first);
240 int32_t amount = display->mDisplayTDMInfo[TDMInfoId]
241 .getAvailableAmount(attr->first)
242 .totalAmount;
243 HDEBUGLOGD(eDebugTDM,
244 "%s : [%s] display:%d,block:%d,axi:%d, amount:%d(%s)",
245 __func__, attr->second.name.string(), display->mType,
246 blockId->first, axi->first, amount,
247 display->isEnabled() ? "used" : "not used");
248 }
249 }
250 }
251 }
252 }
253 }
254
255 return 0;
256 }
257
initDisplaysTDMInfo()258 uint32_t ExynosResourceManagerModule::initDisplaysTDMInfo()
259 {
260 /*
261 * Initialize as predefined value at table
262 * Primary's resource will be changed at setDisplaysTDMInfo() function
263 */
264 for (auto &display : mDisplays) {
265 for (auto attr = HWAttrs.begin(); attr != HWAttrs.end(); attr++) {
266 for (auto blockId = DPUBlocks.begin(); blockId != DPUBlocks.end(); blockId++) {
267 if (attr->second.loadSharing == LS_DPUF) {
268 setupHWResource(attr->first, attr->second.name, blockId->first, AXI_DONT_CARE,
269 display, nullptr, mConstraintRev);
270 } else if (attr->second.loadSharing == LS_DPUF_AXI) {
271 for (auto axi = AXIPorts.begin(); axi != AXIPorts.end(); ++axi) {
272 setupHWResource(attr->first, attr->second.name, blockId->first, axi->first,
273 display, nullptr, mConstraintRev);
274 }
275 }
276 }
277 }
278 }
279
280 return 0;
281 }
282
getSramAmount(tdm_attr_t attr,uint32_t formatProperty,lbWidthIndex_t widthIndex)283 uint32_t getSramAmount(tdm_attr_t attr, uint32_t formatProperty, lbWidthIndex_t widthIndex) {
284 auto it = sramAmountMap.find(sramAmountParams(attr, formatProperty, widthIndex));
285 return (it != sramAmountMap.end()) ? it->second : 0;
286 }
287
calculateHWResourceAmount(ExynosDisplay * display,ExynosMPPSource * mppSrc)288 uint32_t ExynosResourceManagerModule::calculateHWResourceAmount(ExynosDisplay *display,
289 ExynosMPPSource *mppSrc)
290 {
291 uint32_t SRAMtotal = 0;
292
293 if (mppSrc == nullptr) return SRAMtotal;
294
295 if (mppSrc->mSourceType == MPP_SOURCE_LAYER) {
296 ExynosLayer *layer = static_cast<ExynosLayer *>(mppSrc->mSource);
297 if (layer == nullptr) {
298 ALOGE("%s: cannot cast ExynosLayer", __func__);
299 return SRAMtotal;
300 }
301 exynos_image src_img;
302 exynos_image dst_img;
303 layer->setSrcExynosImage(&src_img);
304 layer->setDstExynosImage(&dst_img);
305 layer->setExynosImage(src_img, dst_img);
306 }
307
308 int32_t transform = mppSrc->mSrcImg.transform;
309 int32_t compressType = mppSrc->mSrcImg.compressionInfo.type;
310 bool rotation = (transform & HAL_TRANSFORM_ROT_90) ? true : false;
311
312 int32_t width = mppSrc->mSrcImg.w;
313 int32_t height = mppSrc->mSrcImg.h;
314 uint32_t format = mppSrc->mSrcImg.format;
315 uint32_t formatBPP = 0;
316 if (isFormat10Bit(format))
317 formatBPP = BIT10;
318 else if (isFormat8Bit(format))
319 formatBPP = BIT8;
320
321 /** To find index **/
322 uint32_t formatIndex = 0;
323
324 lbWidthIndex_t widthIndex = LB_W_3073_INF;
325
326 auto findWidthIndex = [&](int32_t w) -> lbWidthIndex_t {
327 for (auto it = LB_WIDTH_INDEX_MAP.begin(); it != LB_WIDTH_INDEX_MAP.end(); it++) {
328 if (w >= it->second.widthDownto && w <= it->second.widthUpto) {
329 return it->first;
330 }
331 }
332 return LB_W_3073_INF;
333 };
334
335 /* Caluclate SRAM amount */
336 if (rotation) {
337 width = height;
338 /* Rotation amount, Only YUV rotation is supported */
339 if (compressType == COMP_TYPE_SBWC) {
340 /* Y and UV width should be aligned and should get sram for each Y and UV */
341 int32_t width_y = pixel_align(width + kSramSBWCRotWidthAlign, kSramSBWCRotWidthAlign);
342 int32_t width_c =
343 pixel_align(width / 2 + kSramSBWCRotWidthAlign, kSramSBWCRotWidthAlign);
344 SRAMtotal += getSramAmount(TDM_ATTR_ROT_90, SBWC_Y, findWidthIndex(width_y));
345 SRAMtotal += getSramAmount(TDM_ATTR_ROT_90, SBWC_UV, findWidthIndex(width_c * 2));
346 } else {
347 /* sramAmountMap has SRAM for both Y and UV */
348 widthIndex = findWidthIndex(width);
349 SRAMtotal += getSramAmount(TDM_ATTR_ROT_90, NON_SBWC_Y | formatBPP, widthIndex);
350 SRAMtotal += getSramAmount(TDM_ATTR_ROT_90, NON_SBWC_UV | formatBPP, widthIndex);
351 }
352 HDEBUGLOGD(eDebugTDM, "+ rotation : %d", SRAMtotal);
353 } else {
354 if (compressType == COMP_TYPE_SBWC) {
355 width = pixel_align(width + kSramSBWCWidthMargin, kSramSBWCWidthAlign);
356 } else if (compressType == COMP_TYPE_AFBC) {
357 /* Align for 8,4Byte/pixel formats */
358 if (formatToBpp(format) > 16) {
359 width = pixel_align(width + kSramAFBC8B4BMargin, kSramAFBC8B4BAlign);
360 } else {
361 /* Align for 2Byte/pixel formats */
362 width = pixel_align(width + kSramAFBC2BMargin, kSramAFBC2BAlign);
363 }
364 }
365 widthIndex = findWidthIndex(width);
366
367 /* AFBC amount */
368 if (compressType == COMP_TYPE_AFBC) {
369 formatIndex = (isFormatRgb(format) ? RGB : 0) | formatBPP;
370 SRAMtotal += getSramAmount(TDM_ATTR_AFBC, formatIndex, widthIndex);
371 HDEBUGLOGD(eDebugTDM, "+ AFBC : %d", SRAMtotal);
372 }
373
374 /* SBWC amount */
375 if (compressType == COMP_TYPE_SBWC) {
376 SRAMtotal += getSramAmount(TDM_ATTR_SBWC, SBWC_Y, widthIndex);
377 SRAMtotal += getSramAmount(TDM_ATTR_SBWC, SBWC_UV, widthIndex);
378 HDEBUGLOGD(eDebugTDM, "+ SBWC : %d", SRAMtotal);
379 }
380 }
381
382 /* ITP (CSC) amount */
383 if (isFormatYUV(format)) {
384 /** ITP has no size difference, Use width index as LB_W_3073_INF **/
385 SRAMtotal += getSramAmount(TDM_ATTR_ITP, formatBPP, LB_W_3073_INF);
386 HDEBUGLOGD(eDebugTDM, "+ YUV : %d", SRAMtotal);
387 }
388
389 /* Scale amount */
390 int srcW = mppSrc->mSrcImg.w;
391 int srcH = mppSrc->mSrcImg.h;
392 int dstW = mppSrc->mDstImg.w;
393 int dstH = mppSrc->mDstImg.h;
394
395 if (!!(transform & HAL_TRANSFORM_ROT_90)) {
396 int tmp = dstW;
397 dstW = dstH;
398 dstH = tmp;
399 }
400
401 bool isScaled = ((srcW != dstW) || (srcH != dstH));
402
403 if (isScaled) {
404 if (formatHasAlphaChannel(format))
405 formatIndex = FORMAT_RGB_MASK;
406 else
407 formatIndex = FORMAT_YUV_MASK;
408
409 /** Scale has no size difference, Use width index as LB_W_3073_INF **/
410 SRAMtotal += getSramAmount(TDM_ATTR_SCALE, formatIndex, LB_W_3073_INF);
411 HDEBUGLOGD(eDebugTDM, "+ Scale : %d", SRAMtotal);
412 }
413
414 for (auto it = HWAttrs.begin(); it != HWAttrs.end(); it++) {
415 uint32_t amount = 0;
416 if (it->first == TDM_ATTR_SRAM_AMOUNT) {
417 amount = SRAMtotal;
418 } else {
419 amount = needHWResource(display, mppSrc->mSrcImg, mppSrc->mDstImg, it->first);
420 }
421 mppSrc->setHWResourceAmount(it->first, amount);
422 }
423
424 HDEBUGLOGD(eDebugTDM,
425 "mppSrc(%p) needed SRAM(%d), SCALE(%d), AFBC(%d), CSC(%d), SBWC(%d), WCG(%d), "
426 "ROT(%d)",
427 mppSrc->mSrcImg.bufferHandle, SRAMtotal,
428 needHWResource(display, mppSrc->mSrcImg, mppSrc->mDstImg, TDM_ATTR_SCALE),
429 needHWResource(display, mppSrc->mSrcImg, mppSrc->mDstImg, TDM_ATTR_AFBC),
430 needHWResource(display, mppSrc->mSrcImg, mppSrc->mDstImg, TDM_ATTR_ITP),
431 needHWResource(display, mppSrc->mSrcImg, mppSrc->mDstImg, TDM_ATTR_SBWC),
432 needHWResource(display, mppSrc->mSrcImg, mppSrc->mDstImg, TDM_ATTR_WCG),
433 needHWResource(display, mppSrc->mSrcImg, mppSrc->mDstImg, TDM_ATTR_ROT_90));
434
435 return SRAMtotal;
436 }
437
otfMppReordering(ExynosDisplay * display,ExynosMPPVector & otfMPPs,struct exynos_image & src,struct exynos_image & dst)438 int32_t ExynosResourceManagerModule::otfMppReordering(ExynosDisplay *display,
439 ExynosMPPVector &otfMPPs,
440 struct exynos_image &src,
441 struct exynos_image &dst)
442 {
443 int orderingType = isAFBCCompressed(src.bufferHandle)
444 ? ORDER_AFBC
445 : (needHdrProcessing(display, src, dst) ? ORDER_WCG : ORDER_AXI);
446
447 int usedAFBCCount[DPU_BLOCK_CNT] = {0};
448 int usedWCGCount[DPU_BLOCK_CNT * AXI_PORT_MAX_CNT] = {0};
449 int usedBlockCount[DPU_BLOCK_CNT] = {0};
450 int usedAXIPortCount[AXI_PORT_MAX_CNT] = {0};
451
452 auto orderPolicy = [&](const void *lhs, const void *rhs) -> bool {
453 if (lhs == NULL || rhs == NULL) {
454 return 0;
455 }
456
457 const ExynosMPPModule *l = (ExynosMPPModule *)lhs;
458 const ExynosMPPModule *r = (ExynosMPPModule *)rhs;
459
460 uint32_t assignedStateL = l->mAssignedState & MPP_ASSIGN_STATE_ASSIGNED;
461 uint32_t assignedStateR = r->mAssignedState & MPP_ASSIGN_STATE_ASSIGNED;
462
463 if (assignedStateL != assignedStateR) return assignedStateL < assignedStateR;
464
465 if (l->mPhysicalType != r->mPhysicalType) return l->mPhysicalType < r->mPhysicalType;
466
467 if (orderingType == ORDER_AFBC) {
468 /* AFBC balancing */
469 if ((l->mAttr & MPP_ATTR_AFBC) != (r->mAttr & MPP_ATTR_AFBC))
470 return (l->mAttr & MPP_ATTR_AFBC) > (r->mAttr & MPP_ATTR_AFBC);
471 if (l->mAttr & MPP_ATTR_AFBC) {
472 /* If layer is AFBC, DPU block that AFBC HW block belongs
473 * which has not been used much should be placed in the front */
474 if (usedAFBCCount[l->mHWBlockId] != usedAFBCCount[r->mHWBlockId])
475 return usedAFBCCount[l->mHWBlockId] < usedAFBCCount[r->mHWBlockId];
476 }
477 } else if (orderingType == ORDER_WCG) {
478 /* WCG balancing */
479 if ((l->mAttr & MPP_ATTR_WCG) != (r->mAttr & MPP_ATTR_WCG))
480 return (l->mAttr & MPP_ATTR_WCG) > (r->mAttr & MPP_ATTR_WCG);
481 if (l->mAttr & MPP_ATTR_WCG) {
482 /* If layer is WCG, DPU block that WCG HW block belongs
483 * which has not been used much should be placed in the front */
484 if (usedWCGCount[l->mHWBlockId * AXI_PORT_MAX_CNT + l->mAXIPortId] !=
485 usedWCGCount[r->mHWBlockId * AXI_PORT_MAX_CNT + r->mAXIPortId])
486 return usedWCGCount[l->mHWBlockId * AXI_PORT_MAX_CNT + l->mAXIPortId] <
487 usedWCGCount[r->mHWBlockId * AXI_PORT_MAX_CNT + r->mAXIPortId];
488 }
489 }
490
491 /* AXI bus balancing */
492 /* AXI port which has not been used much should be placed in the front */
493 if (usedAXIPortCount[l->mAXIPortId] != usedAXIPortCount[r->mAXIPortId]) {
494 return usedAXIPortCount[l->mAXIPortId] < usedAXIPortCount[r->mAXIPortId];
495 }
496 /* IF MPP connected same AXI port, Block balancing should be regarded after */
497 if (usedBlockCount[l->mHWBlockId] != usedBlockCount[r->mHWBlockId])
498 return usedBlockCount[l->mHWBlockId] < usedBlockCount[r->mHWBlockId];
499
500 return l->mPhysicalIndex < r->mPhysicalIndex;
501 };
502
503 for (auto it : otfMPPs) {
504 ExynosMPPModule *mpp = (ExynosMPPModule *)it;
505 uint32_t bId = mpp->getHWBlockId();
506 uint32_t aId = mpp->getAXIPortId();
507 bool isAFBC = false;
508 bool isWCG = false;
509
510 if (mpp->mAssignedState & MPP_ASSIGN_STATE_ASSIGNED) {
511 ExynosMPPSource *mppSrc = mpp->mAssignedSources[0];
512 if ((mppSrc->mSourceType == MPP_SOURCE_LAYER) &&
513 (mppSrc->mSrcImg.bufferHandle != nullptr)) {
514 if ((mpp->mAttr & MPP_ATTR_AFBC) &&
515 (isAFBCCompressed(mppSrc->mSrcImg.bufferHandle))) {
516 isAFBC = true;
517 usedAFBCCount[bId]++;
518 } else if ((mpp->mAttr & MPP_ATTR_WCG) &&
519 (needHdrProcessing(display, mppSrc->mSrcImg, mppSrc->mDstImg))) {
520 isWCG = true;
521 usedWCGCount[bId]++;
522 }
523 } else if (mppSrc->mSourceType == MPP_SOURCE_COMPOSITION_TARGET) {
524 ExynosCompositionInfo *info = (ExynosCompositionInfo *)mppSrc;
525 // ESTEVAN_TBD
526 // if ((mpp->mAttr & MPP_ATTR_AFBC) && (info->mCompressionInfo.type ==
527 // COMP_TYPE_AFBC)) {
528 if ((mpp->mAttr & MPP_ATTR_AFBC) &&
529 (isAFBCCompressed(mppSrc->mSrcImg.bufferHandle))) {
530 isAFBC = true;
531 usedAFBCCount[bId]++;
532 } else if ((mpp->mAttr & MPP_ATTR_WCG) &&
533 (needHdrProcessing(display, info->mSrcImg, info->mDstImg))) {
534 isWCG = true;
535 usedWCGCount[bId]++;
536 }
537 }
538
539 HDEBUGLOGD(eDebugLoadBalancing, "%s: %s is assigned (AFBC:%d, WCG:%d), is %s", __func__,
540 mpp->mName.string(), isAFBC, isWCG,
541 (mppSrc->mSourceType == MPP_SOURCE_LAYER) ? "Layer" : "Client Target");
542 usedBlockCount[bId]++;
543 usedAXIPortCount[aId]++;
544 }
545 }
546
547 HDEBUGLOGD(eDebugLoadBalancing,
548 "Sorting by %s ordering, AFBC(used DPUF0:%d, DPUF1:%d), AXI(used AXI0:%d, AXI1:%d), "
549 "BLOCK(used DPUF0:%d, DPUF1:%d)",
550 (orderingType == ORDER_AFBC) ? "AFBC" : "_AXI", usedAFBCCount[DPUF0],
551 usedAFBCCount[DPUF1], usedAXIPortCount[AXI0], usedAXIPortCount[AXI1],
552 usedBlockCount[DPUF0], usedBlockCount[DPUF1]);
553
554 std::sort(otfMPPs.begin(), otfMPPs.end(), orderPolicy);
555
556 if (hwcCheckDebugMessages(eDebugLoadBalancing)) {
557 String8 after;
558 for (uint32_t i = 0; i < otfMPPs.size(); i++) {
559 ExynosMPPModule *mpp = (ExynosMPPModule *)otfMPPs[i];
560 after.appendFormat("(%s) -> ", mpp->mName.string());
561 }
562
563 ALOGD("%s %p, %s", __func__, src.bufferHandle, after.string());
564 }
565
566 return 0;
567 }
568
isOverlapped(ExynosDisplay * display,ExynosMPPSource * current,ExynosMPPSource * compare)569 bool ExynosResourceManagerModule::isOverlapped(ExynosDisplay *display, ExynosMPPSource *current,
570 ExynosMPPSource *compare) {
571 int CT = current->mDstImg.y - TDM_OVERLAP_MARGIN;
572 CT = (CT < 0) ? 0 : CT;
573 int CB = current->mDstImg.y + current->mDstImg.h + TDM_OVERLAP_MARGIN;
574 CB = (CB > display->mYres) ? display->mYres : CB;
575 int LT = compare->mDstImg.y;
576 int LB = compare->mDstImg.y + compare->mDstImg.h;
577
578 if (((LT <= CT && CT <= LB) || (LT <= CB && CB <= LB)) ||
579 ((CT <= LT && LT <= CB) || (CT < LB && LB <= CB))) {
580 HDEBUGLOGD(eDebugTDM, "%s, current %p and compare %p is overlaped", __func__,
581 current->mSrcImg.bufferHandle, compare->mSrcImg.bufferHandle);
582 return true;
583 }
584
585 return false;
586 }
587
getAmounts(ExynosDisplay * display,uint32_t currentBlockId,uint32_t currentAXIId,ExynosMPP * compOtfMPP,ExynosMPPSource * curSrc,ExynosMPPSource * compSrc,std::array<uint32_t,TDM_ATTR_MAX> & DPUFAmounts,std::array<uint32_t,TDM_ATTR_MAX> & AXIAmounts)588 uint32_t ExynosResourceManagerModule::getAmounts(ExynosDisplay* display, uint32_t currentBlockId,
589 uint32_t currentAXIId, ExynosMPP* compOtfMPP,
590 ExynosMPPSource* curSrc, ExynosMPPSource* compSrc,
591 std::array<uint32_t, TDM_ATTR_MAX>& DPUFAmounts,
592 std::array<uint32_t, TDM_ATTR_MAX>& AXIAmounts) {
593 const uint32_t blockId = compOtfMPP->getHWBlockId();
594 const uint32_t AXIId = compOtfMPP->getAXIPortId();
595 if (currentBlockId == blockId && isOverlapped(display, curSrc, compSrc)) {
596 String8 log;
597 if (hwcCheckDebugMessages(eDebugTDM)) {
598 log.appendFormat("%s", compOtfMPP->mName.string());
599 }
600 for (auto attr = HWAttrs.begin(); attr != HWAttrs.end(); attr++) {
601 uint32_t compareAmount = compSrc->getHWResourceAmount(attr->first);
602 if (hwcCheckDebugMessages(eDebugTDM)) {
603 log.appendFormat(", attr %s DPUF-%d(+ %d)", attr->second.name.string(),
604 DPUFAmounts[attr->first], compareAmount);
605 }
606 DPUFAmounts[attr->first] += compareAmount;
607 if (attr->second.loadSharing == LS_DPUF_AXI && currentAXIId == AXIId) {
608 if (hwcCheckDebugMessages(eDebugTDM)) {
609 log.appendFormat(",AXI-%d(+ %d)", AXIAmounts[attr->first], compareAmount);
610 }
611 AXIAmounts[attr->first] += compareAmount;
612 }
613 }
614 HDEBUGLOGD(eDebugTDM, "%s %s", __func__, log.string());
615 }
616
617 return 0;
618 }
619