• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 #define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
18 
19 #include "ExynosDisplayDrmInterface.h"
20 
21 #include <cutils/properties.h>
22 #include <drm.h>
23 #include <drm/drm_fourcc.h>
24 #include <sys/types.h>
25 #include <xf86drm.h>
26 
27 #include <algorithm>
28 #include <numeric>
29 
30 #include "BrightnessController.h"
31 #include "ExynosHWCDebug.h"
32 #include "ExynosHWCHelper.h"
33 #include "ExynosLayer.h"
34 
35 using namespace std::chrono_literals;
36 
37 constexpr uint32_t MAX_PLANE_NUM = 3;
38 constexpr uint32_t CBCR_INDEX = 1;
39 constexpr float DISPLAY_LUMINANCE_UNIT = 10000;
40 constexpr auto nsecsPerSec = std::chrono::nanoseconds(1s).count();
41 constexpr auto vsyncPeriodTag = "VsyncPeriod";
42 
43 typedef struct _drmModeAtomicReqItem drmModeAtomicReqItem, *drmModeAtomicReqItemPtr;
44 
45 struct _drmModeAtomicReqItem {
46     uint32_t object_id;
47     uint32_t property_id;
48     uint64_t value;
49 };
50 
51 struct _drmModeAtomicReq {
52     uint32_t cursor;
53     uint32_t size_items;
54     drmModeAtomicReqItemPtr items;
55 };
56 
57 using namespace vendor::graphics;
58 
59 extern struct exynos_hwc_control exynosHWCControl;
60 static const int32_t kUmPerInch = 25400;
61 
~FramebufferManager()62 FramebufferManager::~FramebufferManager()
63 {
64     {
65         Mutex::Autolock lock(mMutex);
66         mRmFBThreadRunning = false;
67     }
68     mFlipDone.signal();
69     mRmFBThread.join();
70 }
71 
init(int drmFd)72 void FramebufferManager::init(int drmFd)
73 {
74     mDrmFd = drmFd;
75     mRmFBThreadRunning = true;
76     mRmFBThread = std::thread(&FramebufferManager::removeFBsThreadRoutine, this);
77     pthread_setname_np(mRmFBThread.native_handle(), "RemoveFBsThread");
78 }
79 
getBufHandleFromFd(int fd)80 uint32_t FramebufferManager::getBufHandleFromFd(int fd)
81 {
82     uint32_t gem_handle = 0;
83 
84     int ret = drmPrimeFDToHandle(mDrmFd, fd, &gem_handle);
85     if (ret) {
86         ALOGE("drmPrimeFDToHandle failed with fd %d error %d (%s)", fd, ret, strerror(errno));
87     }
88     return gem_handle;
89 }
90 
addFB2WithModifiers(uint32_t state,uint32_t width,uint32_t height,uint32_t drmFormat,const DrmArray<uint32_t> & handles,const DrmArray<uint32_t> & pitches,const DrmArray<uint32_t> & offsets,const DrmArray<uint64_t> & modifier,uint32_t * buf_id,uint32_t flags)91 int FramebufferManager::addFB2WithModifiers(uint32_t state, uint32_t width, uint32_t height,
92                                             uint32_t drmFormat, const DrmArray<uint32_t> &handles,
93                                             const DrmArray<uint32_t> &pitches,
94                                             const DrmArray<uint32_t> &offsets,
95                                             const DrmArray<uint64_t> &modifier, uint32_t *buf_id,
96                                             uint32_t flags) {
97     if (CC_UNLIKELY(!validateLayerInfo(state, drmFormat, handles, modifier))) {
98         return -EINVAL;
99     }
100 
101     int ret = drmModeAddFB2WithModifiers(mDrmFd, width, height, drmFormat, handles.data(),
102                                          pitches.data(), offsets.data(), modifier.data(), buf_id,
103                                          flags);
104     if (ret) ALOGE("Failed to add fb error %d\n", ret);
105 
106     return ret;
107 }
108 
validateLayerInfo(uint32_t state,uint32_t drmFormat,const DrmArray<uint32_t> & handles,const DrmArray<uint64_t> & modifier)109 bool FramebufferManager::validateLayerInfo(uint32_t state, uint32_t drmFormat,
110                                            const DrmArray<uint32_t> &handles,
111                                            const DrmArray<uint64_t> &modifier) {
112     switch (state) {
113         case exynos_win_config_data::WIN_STATE_RCD:
114             return drmFormat == DRM_FORMAT_C8 && handles[0] != 0 && handles[1] == 0 &&
115                     modifier[0] == 0;
116     }
117 
118     return true;
119 }
120 
checkShrink()121 bool FramebufferManager::checkShrink() {
122     Mutex::Autolock lock(mMutex);
123 
124     mCacheShrinkPending = mCachedLayerBuffers.size() > MAX_CACHED_LAYERS;
125     return mCacheShrinkPending;
126 }
127 
cleanup(const ExynosLayer * layer)128 void FramebufferManager::cleanup(const ExynosLayer *layer) {
129     ATRACE_CALL();
130 
131     Mutex::Autolock lock(mMutex);
132     if (auto it = mCachedLayerBuffers.find(layer); it != mCachedLayerBuffers.end()) {
133         mCleanBuffers.splice(mCleanBuffers.end(), std::move(it->second));
134         mCachedLayerBuffers.erase(it);
135     }
136 }
137 
removeFBsThreadRoutine()138 void FramebufferManager::removeFBsThreadRoutine()
139 {
140     FBList cleanupBuffers;
141     while (true) {
142         {
143             Mutex::Autolock lock(mMutex);
144             if (!mRmFBThreadRunning) {
145                 break;
146             }
147             mFlipDone.wait(mMutex);
148             cleanupBuffers.splice(cleanupBuffers.end(), mCleanBuffers);
149         }
150         ATRACE_NAME("cleanup framebuffers");
151         cleanupBuffers.clear();
152     }
153 }
154 
getBuffer(const exynos_win_config_data & config,uint32_t & fbId)155 int32_t FramebufferManager::getBuffer(const exynos_win_config_data &config, uint32_t &fbId) {
156     ATRACE_CALL();
157     int ret = NO_ERROR;
158     int drmFormat = DRM_FORMAT_UNDEFINED;
159     uint32_t bpp = 0;
160     uint32_t bufferNum, planeNum = 0;
161     uint32_t bufWidth, bufHeight = 0;
162     DrmArray<uint32_t> pitches = {0};
163     DrmArray<uint32_t> offsets = {0};
164     DrmArray<uint64_t> modifiers = {0};
165     DrmArray<uint32_t> handles = {0};
166 
167     if (config.protection) modifiers[0] |= DRM_FORMAT_MOD_PROTECTION;
168 
169     if (config.state == config.WIN_STATE_BUFFER || config.state == config.WIN_STATE_RCD) {
170         bufWidth = config.src.f_w;
171         bufHeight = config.src.f_h;
172         uint32_t compressType = 0;
173         if (config.compression)
174             compressType = AFBC;
175         else if (isFormatSBWC(config.format)) // TODO: b/175381083, change to new API
176             compressType = COMP_ANY;
177 
178         auto exynosFormat = halFormatToExynosFormat(config.format, compressType);
179         if (exynosFormat == nullptr) {
180             ALOGE("%s:: unknown HAL format (%d)", __func__, config.format);
181             return -EINVAL;
182         }
183 
184         drmFormat = exynosFormat->drmFormat;
185         if (drmFormat == DRM_FORMAT_UNDEFINED) {
186             ALOGE("%s:: unknown drm format (%d)", __func__, config.format);
187             return -EINVAL;
188         }
189 
190         bpp = getBytePerPixelOfPrimaryPlane(config.format);
191         if ((bufferNum = exynosFormat->bufferNum) == 0) {
192             ALOGE("%s:: getBufferNumOfFormat(%d) error", __func__, config.format);
193             return -EINVAL;
194         }
195         if (((planeNum = exynosFormat->planeNum) == 0) || (planeNum > MAX_PLANE_NUM)) {
196             ALOGE("%s:: getPlaneNumOfFormat(%d) error, planeNum(%d)", __func__, config.format,
197                   planeNum);
198             return -EINVAL;
199         }
200 
201         fbId = findCachedFbId(config.layer,
202                               [bufferDesc = Framebuffer::BufferDesc{config.buffer_id, drmFormat,
203                                                                     config.protection}](
204                                       auto &buffer) { return buffer->bufferDesc == bufferDesc; });
205         if (fbId != 0) {
206             return NO_ERROR;
207         }
208 
209         if (config.compression) {
210             uint64_t compressed_modifier = AFBC_FORMAT_MOD_BLOCK_SIZE_16x16;
211             switch (config.comp_src) {
212                 case DPP_COMP_SRC_G2D:
213                     compressed_modifier |= AFBC_FORMAT_MOD_SOURCE_G2D;
214                     break;
215                 case DPP_COMP_SRC_GPU:
216                     compressed_modifier |= AFBC_FORMAT_MOD_SOURCE_GPU;
217                     break;
218                 default:
219                     break;
220             }
221             modifiers[0] |= DRM_FORMAT_MOD_ARM_AFBC(compressed_modifier);
222         } else {
223             if (isFormatSBWC(config.format)) {
224                 if (isFormat10BitYUV420(config.format)) {
225                     modifiers[0] |= DRM_FORMAT_MOD_SAMSUNG_SBWC(SBWC_FORMAT_MOD_BLOCK_SIZE_32x5);
226                 } else {
227                     modifiers[0] |= DRM_FORMAT_MOD_SAMSUNG_SBWC(SBWC_FORMAT_MOD_BLOCK_SIZE_32x4);
228                 }
229             }
230         }
231 
232         for (uint32_t bufferIndex = 0; bufferIndex < bufferNum; bufferIndex++) {
233             pitches[bufferIndex] = config.src.f_w * bpp;
234             modifiers[bufferIndex] = modifiers[0];
235             handles[bufferIndex] = getBufHandleFromFd(config.fd_idma[bufferIndex]);
236             if (handles[bufferIndex] == 0) {
237                 return -ENOMEM;
238             }
239         }
240 
241         if ((bufferNum == 1) && (planeNum > bufferNum)) {
242             /* offset for cbcr */
243             offsets[CBCR_INDEX] =
244                     getExynosBufferYLength(config.src.f_w, config.src.f_h, config.format);
245             for (uint32_t planeIndex = 1; planeIndex < planeNum; planeIndex++) {
246                 handles[planeIndex] = handles[0];
247                 pitches[planeIndex] = pitches[0];
248                 modifiers[planeIndex] = modifiers[0];
249             }
250         }
251     } else if (config.state == config.WIN_STATE_COLOR) {
252         bufWidth = config.dst.w;
253         bufHeight = config.dst.h;
254         modifiers[0] |= DRM_FORMAT_MOD_SAMSUNG_COLORMAP;
255         drmFormat = DRM_FORMAT_BGRA8888;
256         bufferNum = 0;
257         handles[0] = 0xff000000;
258         bpp = getBytePerPixelOfPrimaryPlane(HAL_PIXEL_FORMAT_BGRA_8888);
259         pitches[0] = config.dst.w * bpp;
260         fbId = findCachedFbId(config.layer,
261                               [colorDesc = Framebuffer::SolidColorDesc{bufWidth, bufHeight}](
262                                       auto &buffer) { return buffer->colorDesc == colorDesc; });
263         if (fbId != 0) {
264             return NO_ERROR;
265         }
266     } else {
267         ALOGE("%s:: unknown config state(%d)", __func__, config.state);
268         return -EINVAL;
269     }
270 
271     ret = addFB2WithModifiers(config.state, bufWidth, bufHeight, drmFormat, handles, pitches,
272                               offsets, modifiers, &fbId, modifiers[0] ? DRM_MODE_FB_MODIFIERS : 0);
273 
274     for (uint32_t bufferIndex = 0; bufferIndex < bufferNum; bufferIndex++) {
275         freeBufHandle(handles[bufferIndex]);
276     }
277 
278     if (ret) {
279         ALOGE("%s:: Failed to add FB, fb_id(%d), ret(%d), f_w: %d, f_h: %d, dst.w: %d, dst.h: %d, "
280               "format: %d %4.4s, buf_handles[%d, %d, %d, %d], "
281               "pitches[%d, %d, %d, %d], offsets[%d, %d, %d, %d], modifiers[%#" PRIx64 ", %#" PRIx64
282               ", %#" PRIx64 ", %#" PRIx64 "]",
283               __func__, fbId, ret, config.src.f_w, config.src.f_h, config.dst.w, config.dst.h,
284               drmFormat, (char *)&drmFormat, handles[0], handles[1], handles[2], handles[3],
285               pitches[0], pitches[1], pitches[2], pitches[3], offsets[0], offsets[1], offsets[2],
286               offsets[3], modifiers[0], modifiers[1], modifiers[2], modifiers[3]);
287         return ret;
288     }
289 
290     if (config.layer || config.buffer_id) {
291         Mutex::Autolock lock(mMutex);
292         auto &cachedBuffers = mCachedLayerBuffers[config.layer];
293         auto maxCachedBufferSize = MAX_CACHED_BUFFERS_PER_LAYER;
294         if (config.protection && config.layer && config.layer->mM2mMPP) {
295             maxCachedBufferSize = MAX_CACHED_SECURE_BUFFERS_PER_G2D_LAYER;
296         }
297 
298         if (cachedBuffers.size() > maxCachedBufferSize) {
299             ALOGW("FBManager: cached buffers size %zu exceeds limitation(%zu) while adding fbId %d",
300                   cachedBuffers.size(), maxCachedBufferSize, fbId);
301             mCleanBuffers.splice(mCleanBuffers.end(), cachedBuffers);
302         }
303 
304         if (config.state == config.WIN_STATE_COLOR) {
305             cachedBuffers.emplace_front(
306                     new Framebuffer(mDrmFd, fbId,
307                                     Framebuffer::SolidColorDesc{bufWidth, bufHeight}));
308         } else {
309             cachedBuffers.emplace_front(
310                     new Framebuffer(mDrmFd, fbId,
311                                     Framebuffer::BufferDesc{config.buffer_id, drmFormat,
312                                                             config.protection}));
313             mHasSecureFramebuffer |= (isFramebuffer(config.layer) && config.protection);
314         }
315     } else {
316         ALOGW("FBManager: possible leakage fbId %d was created", fbId);
317     }
318 
319     return 0;
320 }
321 
flip(bool hasSecureFrameBuffer)322 void FramebufferManager::flip(bool hasSecureFrameBuffer) {
323     bool needCleanup = false;
324     {
325         Mutex::Autolock lock(mMutex);
326         destroyUnusedLayersLocked();
327         if (!hasSecureFrameBuffer) {
328             destroySecureFramebufferLocked();
329         }
330         needCleanup = mCleanBuffers.size() > 0;
331     }
332 
333     if (needCleanup) {
334         mFlipDone.signal();
335     }
336 }
337 
releaseAll()338 void FramebufferManager::releaseAll()
339 {
340     Mutex::Autolock lock(mMutex);
341     mCachedLayerBuffers.clear();
342     mCleanBuffers.clear();
343 }
344 
freeBufHandle(uint32_t handle)345 void FramebufferManager::freeBufHandle(uint32_t handle) {
346     if (handle == 0) {
347         return;
348     }
349 
350     struct drm_gem_close gem_close {
351         .handle = handle
352     };
353     int ret = drmIoctl(mDrmFd, DRM_IOCTL_GEM_CLOSE, &gem_close);
354     if (ret) {
355         ALOGE("Failed to close gem handle 0x%x with error %d\n", handle, ret);
356     }
357 }
358 
markInuseLayerLocked(const ExynosLayer * layer)359 void FramebufferManager::markInuseLayerLocked(const ExynosLayer *layer) {
360     if (mCacheShrinkPending) {
361         mCachedLayersInuse.insert(layer);
362     }
363 }
364 
destroyUnusedLayersLocked()365 void FramebufferManager::destroyUnusedLayersLocked() {
366     if (!mCacheShrinkPending || mCachedLayersInuse.size() == mCachedLayerBuffers.size()) {
367         mCachedLayersInuse.clear();
368         return;
369     }
370 
371     ALOGW("FBManager: shrink cached layers from %zu to %zu", mCachedLayerBuffers.size(),
372           mCachedLayersInuse.size());
373 
374     for (auto layer = mCachedLayerBuffers.begin(); layer != mCachedLayerBuffers.end();) {
375         if (mCachedLayersInuse.find(layer->first) == mCachedLayersInuse.end()) {
376             mCleanBuffers.splice(mCleanBuffers.end(), std::move(layer->second));
377             layer = mCachedLayerBuffers.erase(layer);
378         } else {
379             ++layer;
380         }
381     }
382 
383     mCachedLayersInuse.clear();
384 }
385 
destroySecureFramebufferLocked()386 void FramebufferManager::destroySecureFramebufferLocked() {
387     if (!mHasSecureFramebuffer) {
388         return;
389     }
390 
391     mHasSecureFramebuffer = false;
392 
393     for (auto &layer : mCachedLayerBuffers) {
394         if (isFramebuffer(layer.first)) {
395             auto &bufferList = layer.second;
396             for (auto it = bufferList.begin(); it != bufferList.end(); ++it) {
397                 auto &buffer = *it;
398                 if (buffer->bufferDesc.isSecure) {
399                     // Assume the latest non-secure buffer in the front
400                     // TODO: have a better way to keep in-used buffers
401                     mCleanBuffers.splice(mCleanBuffers.end(), bufferList, it, bufferList.end());
402                     return;
403                 }
404             }
405         }
406     }
407 }
408 
destroyLayer(ExynosLayer * layer)409 void ExynosDisplayDrmInterface::destroyLayer(ExynosLayer *layer) {
410     mFBManager.cleanup(layer);
411 }
412 
getDisplayIdleTimerSupport(bool & outSupport)413 int32_t ExynosDisplayDrmInterface::getDisplayIdleTimerSupport(bool &outSupport) {
414     auto [ret, support] = mDrmConnector->panel_idle_support().value();
415     if (ret) {
416         ALOGI("no panel_idle_support drm property or invalid value (%d)", ret);
417         outSupport = false;
418     } else {
419         outSupport = (support > 0);
420     }
421 
422     return NO_ERROR;
423 }
424 
getDefaultModeId(int32_t * modeId)425 int32_t ExynosDisplayDrmInterface::getDefaultModeId(int32_t *modeId) {
426     if (modeId == nullptr) return HWC2_ERROR_BAD_PARAMETER;
427 
428     *modeId = mDrmConnector->get_preferred_mode_id();
429     return NO_ERROR;
430 }
431 
ExynosDisplayDrmInterface(ExynosDisplay * exynosDisplay)432 ExynosDisplayDrmInterface::ExynosDisplayDrmInterface(ExynosDisplay *exynosDisplay)
433 {
434     mType = INTERFACE_TYPE_DRM;
435     init(exynosDisplay);
436 }
437 
~ExynosDisplayDrmInterface()438 ExynosDisplayDrmInterface::~ExynosDisplayDrmInterface()
439 {
440     if (mActiveModeState.blob_id)
441         mDrmDevice->DestroyPropertyBlob(mActiveModeState.blob_id);
442     if (mActiveModeState.old_blob_id)
443         mDrmDevice->DestroyPropertyBlob(mActiveModeState.old_blob_id);
444     if (mDesiredModeState.blob_id)
445         mDrmDevice->DestroyPropertyBlob(mDesiredModeState.blob_id);
446     if (mDesiredModeState.old_blob_id)
447         mDrmDevice->DestroyPropertyBlob(mDesiredModeState.old_blob_id);
448     if (mPartialRegionState.blob_id)
449         mDrmDevice->DestroyPropertyBlob(mPartialRegionState.blob_id);
450 }
451 
init(ExynosDisplay * exynosDisplay)452 void ExynosDisplayDrmInterface::init(ExynosDisplay *exynosDisplay)
453 {
454     mExynosDisplay = exynosDisplay;
455     mDrmDevice = NULL;
456     mDrmCrtc = NULL;
457     mDrmConnector = NULL;
458 }
459 
parseBlendEnums(const DrmProperty & property)460 void ExynosDisplayDrmInterface::parseBlendEnums(const DrmProperty &property)
461 {
462     const std::vector<std::pair<uint32_t, const char *>> blendEnums = {
463         {HWC2_BLEND_MODE_NONE, "None"},
464         {HWC2_BLEND_MODE_PREMULTIPLIED, "Pre-multiplied"},
465         {HWC2_BLEND_MODE_COVERAGE, "Coverage"},
466     };
467 
468     ALOGD("Init blend enums");
469     DrmEnumParser::parseEnums(property, blendEnums, mBlendEnums);
470     for (auto &e : mBlendEnums) {
471         ALOGD("blend [hal: %d, drm: %" PRId64 "]", e.first, e.second);
472     }
473 }
474 
parseStandardEnums(const DrmProperty & property)475 void ExynosDisplayDrmInterface::parseStandardEnums(const DrmProperty &property)
476 {
477     const std::vector<std::pair<uint32_t, const char *>> standardEnums = {
478         {HAL_DATASPACE_STANDARD_UNSPECIFIED, "Unspecified"},
479         {HAL_DATASPACE_STANDARD_BT709, "BT709"},
480         {HAL_DATASPACE_STANDARD_BT601_625, "BT601_625"},
481         {HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED, "BT601_625_UNADJUSTED"},
482         {HAL_DATASPACE_STANDARD_BT601_525, "BT601_525"},
483         {HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED, "BT601_525_UNADJUSTED"},
484         {HAL_DATASPACE_STANDARD_BT2020, "BT2020"},
485         {HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE, "BT2020_CONSTANT_LUMINANCE"},
486         {HAL_DATASPACE_STANDARD_BT470M, "BT470M"},
487         {HAL_DATASPACE_STANDARD_FILM, "FILM"},
488         {HAL_DATASPACE_STANDARD_DCI_P3, "DCI-P3"},
489         {HAL_DATASPACE_STANDARD_ADOBE_RGB, "Adobe RGB"},
490     };
491 
492     ALOGD("Init standard enums");
493     DrmEnumParser::parseEnums(property, standardEnums, mStandardEnums);
494     for (auto &e : mStandardEnums) {
495         ALOGD("standard [hal: %d, drm: %" PRId64 "]",
496                 e.first >> HAL_DATASPACE_STANDARD_SHIFT, e.second);
497     }
498 }
499 
parseTransferEnums(const DrmProperty & property)500 void ExynosDisplayDrmInterface::parseTransferEnums(const DrmProperty &property)
501 {
502     const std::vector<std::pair<uint32_t, const char *>> transferEnums = {
503         {HAL_DATASPACE_TRANSFER_UNSPECIFIED, "Unspecified"},
504         {HAL_DATASPACE_TRANSFER_LINEAR, "Linear"},
505         {HAL_DATASPACE_TRANSFER_SRGB, "sRGB"},
506         {HAL_DATASPACE_TRANSFER_SMPTE_170M, "SMPTE 170M"},
507         {HAL_DATASPACE_TRANSFER_GAMMA2_2, "Gamma 2.2"},
508         {HAL_DATASPACE_TRANSFER_GAMMA2_6, "Gamma 2.6"},
509         {HAL_DATASPACE_TRANSFER_GAMMA2_8, "Gamma 2.8"},
510         {HAL_DATASPACE_TRANSFER_ST2084, "ST2084"},
511         {HAL_DATASPACE_TRANSFER_HLG, "HLG"},
512     };
513 
514     ALOGD("Init transfer enums");
515     DrmEnumParser::parseEnums(property, transferEnums, mTransferEnums);
516     for (auto &e : mTransferEnums) {
517         ALOGD("transfer [hal: %d, drm: %" PRId64 "]",
518                 e.first >> HAL_DATASPACE_TRANSFER_SHIFT, e.second);
519     }
520 }
521 
parseRangeEnums(const DrmProperty & property)522 void ExynosDisplayDrmInterface::parseRangeEnums(const DrmProperty &property)
523 {
524     const std::vector<std::pair<uint32_t, const char *>> rangeEnums = {
525         {HAL_DATASPACE_RANGE_UNSPECIFIED, "Unspecified"},
526         {HAL_DATASPACE_RANGE_FULL, "Full"},
527         {HAL_DATASPACE_RANGE_LIMITED, "Limited"},
528         {HAL_DATASPACE_RANGE_EXTENDED, "Extended"},
529     };
530 
531     ALOGD("Init range enums");
532     DrmEnumParser::parseEnums(property, rangeEnums, mRangeEnums);
533     for (auto &e : mRangeEnums) {
534         ALOGD("range [hal: %d, drm: %" PRId64 "]",
535                 e.first >> HAL_DATASPACE_RANGE_SHIFT, e.second);
536     }
537 }
538 
parseColorModeEnums(const DrmProperty & property)539 void ExynosDisplayDrmInterface::parseColorModeEnums(const DrmProperty &property)
540 {
541     const std::vector<std::pair<uint32_t, const char *>> colorModeEnums = {
542         {HAL_COLOR_MODE_NATIVE, "Native"},
543         {HAL_COLOR_MODE_DCI_P3, "DCI-P3"},
544         {HAL_COLOR_MODE_SRGB, "sRGB"},
545     };
546 
547     ALOGD("Init color mode enums");
548     DrmEnumParser::parseEnums(property, colorModeEnums, mColorModeEnums);
549     for (auto &e : mColorModeEnums) {
550         ALOGD("Colormode [hal: %d, drm: %" PRId64 "]", e.first, e.second);
551     }
552 }
553 
parseMipiSyncEnums(const DrmProperty & property)554 void ExynosDisplayDrmInterface::parseMipiSyncEnums(const DrmProperty &property) {
555     const std::vector<std::pair<uint32_t, const char*>> modeEnums = {
556         { toUnderlying(HalMipiSyncType::HAL_MIPI_CMD_SYNC_REFRESH_RATE), "sync_refresh_rate" },
557         { toUnderlying(HalMipiSyncType::HAL_MIPI_CMD_SYNC_LHBM), "sync_lhbm" },
558         { toUnderlying(HalMipiSyncType::HAL_MIPI_CMD_SYNC_GHBM), "sync_ghbm" },
559         { toUnderlying(HalMipiSyncType::HAL_MIPI_CMD_SYNC_BL), "sync_bl" },
560     };
561     DrmEnumParser::parseEnums(property, modeEnums, mMipiSyncEnums);
562     for (auto &e : mMipiSyncEnums) {
563         ALOGD("mipi sync [hal 0x%x, drm: %" PRId64 ", %s]", e.first, e.second,
564               modeEnums[e.first].second);
565     }
566 }
567 
updateMountOrientation()568 void ExynosDisplayDrmInterface::updateMountOrientation()
569 {
570     const std::vector<std::pair<HwcMountOrientation, const char*>> orientationEnums = {
571         { HwcMountOrientation::ROT_0, "Normal" },
572         { HwcMountOrientation::ROT_90, "Left Side Up" },
573         { HwcMountOrientation::ROT_180, "Upside Down" },
574         { HwcMountOrientation::ROT_270, "Right Side Up" },
575     };
576 
577     mExynosDisplay->mMountOrientation = HwcMountOrientation::ROT_0;
578     const DrmProperty &orientation = mDrmConnector->orientation();
579     if (orientation.id() == 0)
580         return;
581 
582     auto [err, drmOrientation] = orientation.value();
583     if (err) {
584         ALOGW("%s failed to get drm prop value, err: %d", __func__, err);
585         return;
586     }
587 
588     for (auto &e : orientationEnums) {
589         uint64_t enumValue;
590         std::tie(enumValue, err) = orientation.GetEnumValueWithName(e.second);
591         if (!err && enumValue == drmOrientation) {
592             mExynosDisplay->mMountOrientation = e.first;
593             return;
594         }
595     }
596 
597     ALOGW("%s ignore unrecoganized orientation %" PRId64, __func__, drmOrientation);
598 }
599 
getDrmDisplayId(uint32_t type,uint32_t index)600 uint32_t ExynosDisplayDrmInterface::getDrmDisplayId(uint32_t type, uint32_t index)
601 {
602     return type+index;
603 }
604 
initDrmDevice(DrmDevice * drmDevice)605 int32_t ExynosDisplayDrmInterface::initDrmDevice(DrmDevice *drmDevice)
606 {
607     if (mExynosDisplay == NULL) {
608         ALOGE("mExynosDisplay is not set");
609         return -EINVAL;
610     }
611     if ((mDrmDevice = drmDevice) == NULL) {
612         ALOGE("drmDevice is NULL");
613         return -EINVAL;
614     }
615 
616     mFBManager.init(mDrmDevice->fd());
617 
618     uint32_t drmDisplayId = getDrmDisplayId(mExynosDisplay->mType, mExynosDisplay->mIndex);
619 
620     mReadbackInfo.init(mDrmDevice, drmDisplayId);
621     if ((mDrmCrtc = mDrmDevice->GetCrtcForDisplay(drmDisplayId)) == NULL) {
622         ALOGE("%s:: GetCrtcForDisplay is NULL (id: %d)",
623                 mExynosDisplay->mDisplayName.string(), drmDisplayId);
624         return -EINVAL;
625     }
626     if ((mDrmConnector = mDrmDevice->GetConnectorForDisplay(drmDisplayId)) == NULL) {
627         ALOGE("%s:: GetConnectorForDisplay is NULL (id: %d)",
628                 mExynosDisplay->mDisplayName.string(), drmDisplayId);
629         return -EINVAL;
630     }
631 
632     ALOGD("%s:: display type: %d, index: %d, drmDisplayId: %d, "
633             "crtc id: %d, connector id: %d",
634             __func__, mExynosDisplay->mType, mExynosDisplay->mIndex,
635             drmDisplayId, mDrmCrtc->id(), mDrmConnector->id());
636 
637     /* Mapping ExynosMPP resource with DPP Planes */
638     uint32_t numWindow = 0;
639     for (uint32_t i = 0; i < mDrmDevice->planes().size(); i++) {
640         auto &plane = mDrmDevice->planes().at(i);
641         uint32_t plane_id = plane->id();
642 
643         if (!plane->zpos_property().is_immutable()) {
644             /* Plane can be used for composition */
645             ExynosMPP *exynosMPP =
646                 mExynosDisplay->mResourceManager->getOtfMPPWithChannel(i);
647             if (exynosMPP == NULL)
648                 HWC_LOGE(mExynosDisplay, "getOtfMPPWithChannel fail, ch(%d)", plane_id);
649             mExynosMPPsForPlane[plane_id] = exynosMPP;
650             numWindow++;
651         } else {
652             /*
653              * Plane is special purpose plane which cannot be used for compositon.
654              * It's zpos property is immutable.
655              */
656             mExynosMPPsForPlane[plane_id] = NULL;
657         }
658     }
659     setMaxWindowNum(numWindow);
660 
661     if (mExynosDisplay->mMaxWindowNum != getMaxWindowNum()) {
662         ALOGE("%s:: Invalid max window number (mMaxWindowNum: %d, getMaxWindowNum(): %d",
663                 __func__, mExynosDisplay->mMaxWindowNum, getMaxWindowNum());
664         return -EINVAL;
665     }
666 
667     getLowPowerDrmModeModeInfo();
668 
669     mDrmVSyncWorker.Init(mDrmDevice, drmDisplayId);
670     mDrmVSyncWorker.RegisterCallback(std::shared_ptr<VsyncCallback>(this));
671 
672     if (!mDrmDevice->planes().empty()) {
673         auto &plane = mDrmDevice->planes().front();
674         parseBlendEnums(plane->blend_property());
675         parseStandardEnums(plane->standard_property());
676         parseTransferEnums(plane->transfer_property());
677         parseRangeEnums(plane->range_property());
678     }
679 
680     chosePreferredConfig();
681 
682     parseColorModeEnums(mDrmCrtc->color_mode_property());
683     parseMipiSyncEnums(mDrmConnector->mipi_sync());
684     updateMountOrientation();
685 
686     if (mExynosDisplay->mBrightnessController &&
687             mExynosDisplay->mBrightnessController->initDrm(*mDrmDevice, *mDrmConnector)) {
688         ALOGW("%s failed to init brightness controller", __func__);
689     }
690 
691     return NO_ERROR;
692 }
693 
694 
Callback(int display,int64_t timestamp)695 void ExynosDisplayDrmInterface::Callback(
696         int display, int64_t timestamp)
697 {
698     {
699         Mutex::Autolock lock(mExynosDisplay->getDisplayMutex());
700         bool configApplied = mVsyncCallback.Callback(display, timestamp);
701 
702         if (configApplied) {
703             if (mVsyncCallback.getDesiredVsyncPeriod()) {
704                 mExynosDisplay->resetConfigRequestStateLocked(mActiveModeState.mode.id());
705                 mDrmConnector->set_active_mode(mActiveModeState.mode);
706                 mVsyncCallback.resetDesiredVsyncPeriod();
707             }
708 
709             /*
710              * Disable vsync if vsync config change is done
711              */
712             if (!mVsyncCallback.getVSyncEnabled()) {
713                 mDrmVSyncWorker.VSyncControl(false);
714                 mVsyncCallback.resetVsyncTimeStamp();
715             }
716         } else {
717             mExynosDisplay->updateConfigRequestAppliedTime();
718         }
719 
720         if (!mExynosDisplay->mPlugState || !mVsyncCallback.getVSyncEnabled()) {
721             return;
722         }
723     }
724 
725     ExynosDevice *exynosDevice = mExynosDisplay->mDevice;
726 
727     if (exynosDevice->onVsync_2_4(mExynosDisplay->mDisplayId, timestamp,
728                                   mExynosDisplay->mVsyncPeriod)) {
729         ATRACE_INT(vsyncPeriodTag, static_cast<int32_t>(mExynosDisplay->mVsyncPeriod));
730         return;
731     }
732 
733     exynosDevice->onVsync(mExynosDisplay->mDisplayId, timestamp);
734 }
735 
Callback(int display,int64_t timestamp)736 bool ExynosDisplayDrmInterface::ExynosVsyncCallback::Callback(
737         int display, int64_t timestamp)
738 {
739     /*
740      * keep vsync period if mVsyncTimeStamp
741      * is not initialized since vsync is enabled
742      */
743     if (mVsyncTimeStamp > 0) {
744         mVsyncPeriod = timestamp - mVsyncTimeStamp;
745     }
746 
747     mVsyncTimeStamp = timestamp;
748 
749     /* There was no config chage request */
750     if (!mDesiredVsyncPeriod)
751         return true;
752 
753     /*
754      * mDesiredVsyncPeriod is nanoseconds
755      * Compare with 20% margin
756      */
757     if (abs(static_cast<int32_t>(mDesiredVsyncPeriod - mVsyncPeriod)) < (mDesiredVsyncPeriod / 5))
758         return true;
759 
760     return false;
761 }
762 
getLowPowerDrmModeModeInfo()763 int32_t ExynosDisplayDrmInterface::getLowPowerDrmModeModeInfo() {
764     auto mode = mDrmConnector->lp_mode();
765 
766     if (!mode.clock()) {
767         return HWC2_ERROR_UNSUPPORTED;
768     }
769 
770     mDozeDrmMode = mode;
771 
772     return NO_ERROR;
773 }
774 
setLowPowerMode()775 int32_t ExynosDisplayDrmInterface::setLowPowerMode() {
776     if (!isDozeModeAvailable()) {
777         return HWC2_ERROR_UNSUPPORTED;
778     }
779 
780     uint32_t mm_width = mDrmConnector->mm_width();
781     uint32_t mm_height = mDrmConnector->mm_height();
782 
783     mExynosDisplay->mXres = mDozeDrmMode.h_display();
784     mExynosDisplay->mYres = mDozeDrmMode.v_display();
785     // in nanoseconds
786     mExynosDisplay->mVsyncPeriod = nsecsPerSec / mDozeDrmMode.v_refresh();
787     // Dots per 1000 inches
788     mExynosDisplay->mXdpi = mm_width ? (mDozeDrmMode.h_display() * kUmPerInch) / mm_width : -1;
789     // Dots per 1000 inches
790     mExynosDisplay->mYdpi = mm_height ? (mDozeDrmMode.v_display() * kUmPerInch) / mm_height : -1;
791 
792     return setActiveDrmMode(mDozeDrmMode);
793 }
794 
setPowerMode(int32_t mode)795 int32_t ExynosDisplayDrmInterface::setPowerMode(int32_t mode)
796 {
797     int ret = 0;
798     uint64_t dpms_value = 0;
799     if (mode == HWC_POWER_MODE_OFF) {
800         dpms_value = DRM_MODE_DPMS_OFF;
801     } else {
802         dpms_value = DRM_MODE_DPMS_ON;
803     }
804 
805     const DrmProperty &prop = mDrmConnector->dpms_property();
806     if ((ret = drmModeConnectorSetProperty(mDrmDevice->fd(), mDrmConnector->id(), prop.id(),
807             dpms_value)) != NO_ERROR) {
808         HWC_LOGE(mExynosDisplay, "setPower mode ret (%d)", ret);
809     }
810 
811     return ret;
812 }
813 
setVsyncEnabled(uint32_t enabled)814 int32_t ExynosDisplayDrmInterface::setVsyncEnabled(uint32_t enabled)
815 {
816     if (enabled == HWC2_VSYNC_ENABLE) {
817         mDrmVSyncWorker.VSyncControl(true);
818     } else {
819         if (mVsyncCallback.getDesiredVsyncPeriod() == 0)
820             mDrmVSyncWorker.VSyncControl(false);
821     }
822 
823     mVsyncCallback.enableVSync(HWC2_VSYNC_ENABLE == enabled);
824 
825     ExynosDevice *exynosDevice = mExynosDisplay->mDevice;
826     if (exynosDevice->isCallbackAvailable(HWC2_CALLBACK_VSYNC_2_4)) {
827         ATRACE_INT(vsyncPeriodTag, 0);
828     }
829 
830     return NO_ERROR;
831 }
832 
chosePreferredConfig()833 int32_t ExynosDisplayDrmInterface::chosePreferredConfig()
834 {
835     uint32_t num_configs = 0;
836     int32_t err = getDisplayConfigs(&num_configs, NULL);
837     if (err != HWC2_ERROR_NONE || !num_configs)
838         return err;
839 
840     int32_t config = -1;
841     char modeStr[PROPERTY_VALUE_MAX] = "\0";
842     int32_t width = 0, height = 0, fps = 0;
843     if (property_get("vendor.display.preferred_mode", modeStr, "") > 0 &&
844         sscanf(modeStr, "%dx%d@%d", &width, &height, &fps) == 3) {
845         err = mExynosDisplay->lookupDisplayConfigs(width, height, fps, &config);
846     } else {
847         err = HWC2_ERROR_BAD_CONFIG;
848     }
849 
850     const int32_t drmPreferredConfig = mDrmConnector->get_preferred_mode_id();
851     if (err != HWC2_ERROR_NONE) {
852         config = drmPreferredConfig;
853     }
854     ALOGI("Preferred mode id: %d(%s), state: %d", config, modeStr, mDrmConnector->state());
855 
856     auto &configs = mExynosDisplay->mDisplayConfigs;
857     if (config != drmPreferredConfig &&
858         (configs[config].width != configs[drmPreferredConfig].width ||
859          configs[config].height != configs[drmPreferredConfig].height)) {
860         // HWC cannot send a resolution change commit here until 1st frame update because of
861         // some panels requirement. Therefore, it calls setActiveConfigWithConstraints() help
862         // set mDesiredModeState correctly, and then trigger modeset in the 1s frame update.
863         if ((err = setActiveConfigWithConstraints(config)) < 0) {
864             ALOGE("failed to setActiveConfigWithConstraints(), err %d", err);
865             return err;
866         }
867     } else {
868         if ((err = setActiveConfig(config)) < 0) {
869             ALOGE("failed to set default config, err %d", err);
870             return err;
871         }
872     }
873 
874     return mExynosDisplay->updateInternalDisplayConfigVariables(config);
875 }
876 
getDisplayConfigs(uint32_t * outNumConfigs,hwc2_config_t * outConfigs)877 int32_t ExynosDisplayDrmInterface::getDisplayConfigs(
878         uint32_t* outNumConfigs,
879         hwc2_config_t* outConfigs)
880 {
881     if (!outConfigs) {
882         int ret = mDrmConnector->UpdateModes();
883         if (ret) {
884             ALOGE("Failed to update display modes %d", ret);
885             return HWC2_ERROR_BAD_DISPLAY;
886         }
887         if (mDrmConnector->state() == DRM_MODE_CONNECTED)
888             mExynosDisplay->mPlugState = true;
889         else
890             mExynosDisplay->mPlugState = false;
891 
892         dumpDisplayConfigs();
893 
894         mExynosDisplay->mDisplayConfigs.clear();
895 
896         uint32_t mm_width = mDrmConnector->mm_width();
897         uint32_t mm_height = mDrmConnector->mm_height();
898 
899         /* key: (width<<32 | height) */
900         std::map<uint64_t, uint32_t> groupIds;
901         uint32_t groupId = 0;
902         uint32_t min_vsync_period = UINT_MAX;
903 
904         for (const DrmMode &mode : mDrmConnector->modes()) {
905             displayConfigs_t configs;
906             configs.vsyncPeriod = nsecsPerSec/ mode.v_refresh();
907             configs.width = mode.h_display();
908             configs.height = mode.v_display();
909             uint64_t key = ((uint64_t)configs.width<<32) | configs.height;
910             auto it = groupIds.find(key);
911             if (it != groupIds.end()) {
912                 configs.groupId = it->second;
913             } else {
914                 configs.groupId = groupId;
915                 groupIds.insert(std::make_pair(key, groupId));
916                 groupId++;
917             }
918 
919             // Dots per 1000 inches
920             configs.Xdpi = mm_width ? (mode.h_display() * kUmPerInch) / mm_width : -1;
921             // Dots per 1000 inches
922             configs.Ydpi = mm_height ? (mode.v_display() * kUmPerInch) / mm_height : -1;
923             // find min vsync period
924             if (configs.vsyncPeriod <= min_vsync_period) min_vsync_period = configs.vsyncPeriod;
925             mExynosDisplay->mDisplayConfigs.insert(std::make_pair(mode.id(), configs));
926             ALOGD("config group(%d), w(%d), h(%d), vsync(%d), xdpi(%d), ydpi(%d)",
927                     configs.groupId, configs.width, configs.height,
928                     configs.vsyncPeriod, configs.Xdpi, configs.Ydpi);
929         }
930         mExynosDisplay->setMinDisplayVsyncPeriod(min_vsync_period);
931     }
932 
933     uint32_t num_modes = static_cast<uint32_t>(mDrmConnector->modes().size());
934     if (!outConfigs) {
935         *outNumConfigs = num_modes;
936         return HWC2_ERROR_NONE;
937     }
938 
939     uint32_t idx = 0;
940 
941     for (const DrmMode &mode : mDrmConnector->modes()) {
942         if (idx >= *outNumConfigs)
943             break;
944         outConfigs[idx++] = mode.id();
945     }
946     *outNumConfigs = idx;
947 
948     return 0;
949 }
950 
dumpDisplayConfigs()951 void ExynosDisplayDrmInterface::dumpDisplayConfigs()
952 {
953     uint32_t num_modes = static_cast<uint32_t>(mDrmConnector->modes().size());
954     for (uint32_t i = 0; i < num_modes; i++) {
955         auto mode = mDrmConnector->modes().at(i);
956         ALOGD("%s display config[%d] %s:: id(%d), clock(%d), flags(%d), type(%d)",
957                 mExynosDisplay->mDisplayName.string(), i, mode.name().c_str(), mode.id(), mode.clock(), mode.flags(), mode.type());
958         ALOGD("\th_display(%d), h_sync_start(%d), h_sync_end(%d), h_total(%d), h_skew(%d)",
959                 mode.h_display(), mode.h_sync_start(), mode.h_sync_end(), mode.h_total(), mode.h_skew());
960         ALOGD("\tv_display(%d), v_sync_start(%d), v_sync_end(%d), v_total(%d), v_scan(%d), v_refresh(%f)",
961                 mode.v_display(), mode.v_sync_start(), mode.v_sync_end(), mode.v_total(), mode.v_scan(), mode.v_refresh());
962 
963     }
964 }
965 
getDisplayVsyncPeriod(hwc2_vsync_period_t * outVsyncPeriod)966 int32_t ExynosDisplayDrmInterface::getDisplayVsyncPeriod(hwc2_vsync_period_t* outVsyncPeriod)
967 {
968     return HWC2_ERROR_UNSUPPORTED;
969 }
970 
getConfigChangeDuration()971 int32_t ExynosDisplayDrmInterface::getConfigChangeDuration()
972 {
973     const auto [ret, duration] = mDrmConnector->vrr_switch_duration().value();
974 
975     if (!ret && duration > 0) {
976         return duration;
977     }
978 
979     return 2;
980 };
981 
getVsyncAppliedTime(hwc2_config_t config,int64_t * actualChangeTime)982 int32_t ExynosDisplayDrmInterface::getVsyncAppliedTime(
983         hwc2_config_t config, int64_t* actualChangeTime)
984 {
985     if (mDrmCrtc->adjusted_vblank_property().id() == 0) {
986         uint64_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
987         *actualChangeTime = currentTime +
988             (mExynosDisplay->mVsyncPeriod) * getConfigChangeDuration();
989         return HWC2_ERROR_NONE;
990     }
991 
992     int ret = 0;
993     if ((ret = mDrmDevice->UpdateCrtcProperty(*mDrmCrtc,
994             &mDrmCrtc->adjusted_vblank_property())) != 0) {
995         HWC_LOGE(mExynosDisplay, "Failed to update vblank property");
996         return ret;
997     }
998 
999     uint64_t timestamp;
1000     std::tie(ret, timestamp) = mDrmCrtc->adjusted_vblank_property().value();
1001     if (ret < 0) {
1002         HWC_LOGE(mExynosDisplay, "Failed to get vblank property");
1003         return ret;
1004     }
1005 
1006     *actualChangeTime = static_cast<int64_t>(timestamp);
1007     return HWC2_ERROR_NONE;
1008 }
1009 
supportDataspace(int32_t dataspace)1010 bool ExynosDisplayDrmInterface::supportDataspace(int32_t dataspace)
1011 {
1012     bool supportStandard = false;
1013     bool supportTransfer = false;
1014     bool supportRange = false;
1015 
1016     /* Check supported standard */
1017     for (auto &e : mStandardEnums) {
1018         if (e.first & dataspace)
1019             supportStandard = true;
1020     }
1021 
1022     /* Check supported transfer */
1023     for (auto &e : mTransferEnums) {
1024         if (e.first & dataspace)
1025             supportTransfer = true;
1026     }
1027 
1028     /* Check supported range */
1029     for (auto &e : mRangeEnums) {
1030         if (e.first & dataspace)
1031             supportRange = true;
1032     }
1033 
1034     return supportStandard && supportTransfer && supportRange;
1035 }
1036 
getColorModes(uint32_t * outNumModes,int32_t * outModes)1037 int32_t ExynosDisplayDrmInterface::getColorModes(uint32_t *outNumModes, int32_t *outModes)
1038 {
1039     if (mDrmCrtc->color_mode_property().id() == 0) {
1040         *outNumModes = 1;
1041 
1042         if (outModes != NULL) {
1043             outModes[0] = HAL_COLOR_MODE_NATIVE;
1044         }
1045         return HWC2_ERROR_NONE;
1046     }
1047 
1048     uint32_t colorNum = 0;
1049     for (auto &e : mColorModeEnums) {
1050         if (outModes != NULL) {
1051             outModes[colorNum] = e.first;
1052         }
1053         colorNum++;
1054         ALOGD("Colormode [hal: %d, drm: %" PRId64 "]", e.first, e.second);
1055     }
1056     *outNumModes = colorNum;
1057 
1058     return HWC2_ERROR_NONE;
1059 }
1060 
setColorMode(int32_t mode)1061 int32_t ExynosDisplayDrmInterface::setColorMode(int32_t mode)
1062 {
1063     int ret = 0;
1064 
1065     if (mDrmCrtc->color_mode_property().id() == 0) {
1066         return HWC2_ERROR_NONE;
1067     }
1068 
1069     DrmModeAtomicReq drmReq(this);
1070 
1071     if ((ret = drmReq.atomicAddProperty(mDrmCrtc->id(),
1072                                         mDrmCrtc->color_mode_property(), mode)) < 0)
1073         return ret;
1074 
1075     if ((ret = drmReq.commit(0, true)) < 0)
1076         return ret;
1077 
1078     return HWC2_ERROR_NONE;
1079 }
1080 
setActiveConfigWithConstraints(hwc2_config_t config,bool test)1081 int32_t ExynosDisplayDrmInterface::setActiveConfigWithConstraints(
1082         hwc2_config_t config, bool test)
1083 {
1084     ALOGD("%s:: %s config(%d) test(%d)", __func__, mExynosDisplay->mDisplayName.string(), config,
1085           test);
1086     auto mode = std::find_if(mDrmConnector->modes().begin(), mDrmConnector->modes().end(),
1087             [config](DrmMode const &m) { return m.id() == config;});
1088     if (mode == mDrmConnector->modes().end()) {
1089         HWC_LOGE(mExynosDisplay, "Could not find active mode for %d", config);
1090         return HWC2_ERROR_BAD_CONFIG;
1091     }
1092 
1093     if ((mActiveModeState.blob_id != 0) &&
1094         (mActiveModeState.mode.id() == config)) {
1095         ALOGD("%s:: same mode %d", __func__, config);
1096         /* trigger resetConfigRequestStateLocked() */
1097         mVsyncCallback.setDesiredVsyncPeriod(nsecsPerSec / mActiveModeState.mode.v_refresh());
1098         mDrmVSyncWorker.VSyncControl(true);
1099         return HWC2_ERROR_NONE;
1100     }
1101 
1102     if (mDesiredModeState.needsModeSet()) {
1103         ALOGD("Previous mode change request is not applied");
1104     }
1105 
1106     int32_t ret = HWC2_ERROR_NONE;
1107     DrmModeAtomicReq drmReq(this);
1108     uint32_t modeBlob = 0;
1109     if (mDesiredModeState.mode.id() != config) {
1110         if ((ret = createModeBlob(*mode, modeBlob)) != NO_ERROR) {
1111             HWC_LOGE(mExynosDisplay, "%s: Fail to set mode state",
1112                     __func__);
1113             return HWC2_ERROR_BAD_CONFIG;
1114         }
1115     }
1116     const auto isResSwitch =
1117             (mActiveModeState.blob_id != 0) && mActiveModeState.isFullModeSwitch(*mode);
1118 
1119     if (!test) {
1120         if (modeBlob) { /* only replace desired mode if it has changed */
1121             mDesiredModeState.setMode(*mode, modeBlob, drmReq);
1122         } else {
1123             ALOGD("%s:: same desired mode %d", __func__, config);
1124         }
1125     } else {
1126         if (!isResSwitch) {
1127             ret = setDisplayMode(drmReq, modeBlob ? modeBlob : mDesiredModeState.blob_id);
1128             if (ret < 0) {
1129                 HWC_LOGE(mExynosDisplay, "%s: Fail to apply display mode", __func__);
1130                 return ret;
1131             }
1132             ret = drmReq.commit(DRM_MODE_ATOMIC_TEST_ONLY, true);
1133             if (ret) {
1134                 drmReq.addOldBlob(modeBlob);
1135                 HWC_LOGE(mExynosDisplay,
1136                          "%s:: Failed to commit pset ret=%d in applyDisplayMode()\n", __func__,
1137                          ret);
1138                 return ret;
1139             }
1140         }
1141 
1142         if (modeBlob) {
1143             mDrmDevice->DestroyPropertyBlob(modeBlob);
1144         }
1145     }
1146     return HWC2_ERROR_NONE;
1147 }
setActiveDrmMode(DrmMode const & mode)1148 int32_t ExynosDisplayDrmInterface::setActiveDrmMode(DrmMode const &mode) {
1149     /* Don't skip when power was off */
1150     if (!(mExynosDisplay->mSkipFrame) && (mActiveModeState.blob_id != 0) &&
1151         (mActiveModeState.mode.id() == mode.id()) && !mActiveModeState.needsModeSet()) {
1152         ALOGD("%s:: same mode %d", __func__, mode.id());
1153         return HWC2_ERROR_NONE;
1154     }
1155 
1156     int32_t ret = HWC2_ERROR_NONE;
1157     uint32_t modeBlob;
1158     if ((ret = createModeBlob(mode, modeBlob)) != NO_ERROR) {
1159         HWC_LOGE(mExynosDisplay, "%s: Fail to set mode state",
1160                 __func__);
1161         return HWC2_ERROR_BAD_CONFIG;
1162     }
1163 
1164     DrmModeAtomicReq drmReq(this);
1165 
1166     uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
1167     bool reconfig = false;
1168 
1169     if (mActiveModeState.isFullModeSwitch(mode)) {
1170         reconfig = true;
1171     }
1172 
1173     if ((ret = setDisplayMode(drmReq, modeBlob)) != NO_ERROR) {
1174         drmReq.addOldBlob(modeBlob);
1175         HWC_LOGE(mExynosDisplay, "%s: Fail to apply display mode",
1176                 __func__);
1177         return ret;
1178     }
1179 
1180     if ((ret = drmReq.commit(flags, true))) {
1181         drmReq.addOldBlob(modeBlob);
1182         HWC_LOGE(mExynosDisplay, "%s:: Failed to commit pset ret=%d in applyDisplayMode()\n",
1183                 __func__, ret);
1184         return ret;
1185     }
1186 
1187     mDrmConnector->set_active_mode(mode);
1188     mActiveModeState.setMode(mode, modeBlob, drmReq);
1189     mActiveModeState.clearPendingModeState();
1190 
1191     if (reconfig) {
1192         mDrmConnector->ResetLpMode();
1193         getLowPowerDrmModeModeInfo();
1194     }
1195 
1196     return HWC2_ERROR_NONE;
1197 }
1198 
setActiveConfig(hwc2_config_t config)1199 int32_t ExynosDisplayDrmInterface::setActiveConfig(hwc2_config_t config) {
1200     auto mode = std::find_if(mDrmConnector->modes().begin(), mDrmConnector->modes().end(),
1201                              [config](DrmMode const &m) { return m.id() == config; });
1202     if (mode == mDrmConnector->modes().end()) {
1203         HWC_LOGE(mExynosDisplay, "Could not find active mode for %d", config);
1204         return HWC2_ERROR_BAD_CONFIG;
1205     }
1206 
1207     mExynosDisplay->updateAppliedActiveConfig(config, systemTime(SYSTEM_TIME_MONOTONIC));
1208     if (!setActiveDrmMode(*mode)) {
1209         ALOGI("%s:: %s config(%d)", __func__, mExynosDisplay->mDisplayName.string(), config);
1210     } else {
1211         ALOGE("%s:: %s config(%d) failed", __func__, mExynosDisplay->mDisplayName.string(), config);
1212     }
1213 
1214     return 0;
1215 }
1216 
getPanelResolution()1217 int32_t ExynosDisplayDrmInterface::getPanelResolution() {
1218     for (auto it = mDrmConnector->modes().begin(); it != mDrmConnector->modes().end(); it++) {
1219         if (it->h_display() * it->v_display() > mPanelResolutionHsize * mPanelResolutionVsize) {
1220             mPanelResolutionHsize = it->h_display();
1221             mPanelResolutionVsize = it->v_display();
1222         }
1223     }
1224     return 0;
1225 }
1226 
createModeBlob(const DrmMode & mode,uint32_t & modeBlob)1227 int32_t ExynosDisplayDrmInterface::createModeBlob(const DrmMode &mode,
1228         uint32_t &modeBlob)
1229 {
1230     struct drm_mode_modeinfo drm_mode;
1231     memset(&drm_mode, 0, sizeof(drm_mode));
1232     mode.ToDrmModeModeInfo(&drm_mode);
1233 
1234     modeBlob = 0;
1235     int ret = mDrmDevice->CreatePropertyBlob(&drm_mode, sizeof(drm_mode),
1236             &modeBlob);
1237     if (ret) {
1238         HWC_LOGE(mExynosDisplay, "Failed to create mode property blob %d", ret);
1239         return ret;
1240     }
1241 
1242     return NO_ERROR;
1243 }
1244 
setDisplayMode(DrmModeAtomicReq & drmReq,const uint32_t modeBlob)1245 int32_t ExynosDisplayDrmInterface::setDisplayMode(
1246         DrmModeAtomicReq &drmReq, const uint32_t modeBlob)
1247 {
1248     int ret = NO_ERROR;
1249 
1250     if ((ret = drmReq.atomicAddProperty(mDrmCrtc->id(),
1251            mDrmCrtc->active_property(), 1)) < 0)
1252         return ret;
1253 
1254     if ((ret = drmReq.atomicAddProperty(mDrmCrtc->id(),
1255             mDrmCrtc->mode_property(), modeBlob)) < 0)
1256         return ret;
1257 
1258     if ((ret = drmReq.atomicAddProperty(mDrmConnector->id(),
1259             mDrmConnector->crtc_id_property(), mDrmCrtc->id())) < 0)
1260         return ret;
1261 
1262     return NO_ERROR;
1263 }
1264 
setCursorPositionAsync(uint32_t x_pos,uint32_t y_pos)1265 int32_t ExynosDisplayDrmInterface::setCursorPositionAsync(uint32_t x_pos, uint32_t y_pos)
1266 {
1267     return 0;
1268 }
1269 
updateHdrCapabilities()1270 int32_t ExynosDisplayDrmInterface::updateHdrCapabilities()
1271 {
1272     /* Init member variables */
1273     mExynosDisplay->mHdrTypes.clear();
1274     mExynosDisplay->mMaxLuminance = 0;
1275     mExynosDisplay->mMaxAverageLuminance = 0;
1276     mExynosDisplay->mMinLuminance = 0;
1277 
1278     const DrmProperty &prop_max_luminance = mDrmConnector->max_luminance();
1279     const DrmProperty &prop_max_avg_luminance = mDrmConnector->max_avg_luminance();
1280     const DrmProperty &prop_min_luminance = mDrmConnector->min_luminance();
1281     const DrmProperty &prop_hdr_formats = mDrmConnector->hdr_formats();
1282 
1283     int ret = 0;
1284     uint64_t max_luminance = 0;
1285     uint64_t max_avg_luminance = 0;
1286     uint64_t min_luminance = 0;
1287     uint64_t hdr_formats = 0;
1288 
1289     if ((prop_max_luminance.id() == 0) ||
1290         (prop_max_avg_luminance.id() == 0) ||
1291         (prop_min_luminance.id() == 0) ||
1292         (prop_hdr_formats.id() == 0)) {
1293         ALOGE("%s:: there is no property for hdrCapabilities (max_luminance: %d, max_avg_luminance: %d, min_luminance: %d, hdr_formats: %d",
1294                 __func__, prop_max_luminance.id(), prop_max_avg_luminance.id(),
1295                 prop_min_luminance.id(), prop_hdr_formats.id());
1296         return -1;
1297     }
1298 
1299     std::tie(ret, max_luminance) = prop_max_luminance.value();
1300     if (ret < 0) {
1301         HWC_LOGE(mExynosDisplay, "%s:: there is no max_luminance (ret = %d)",
1302                 __func__, ret);
1303         return -1;
1304     }
1305     mExynosDisplay->mMaxLuminance = (float)max_luminance / DISPLAY_LUMINANCE_UNIT;
1306 
1307     std::tie(ret, max_avg_luminance) = prop_max_avg_luminance.value();
1308     if (ret < 0) {
1309         HWC_LOGE(mExynosDisplay, "%s:: there is no max_avg_luminance (ret = %d)",
1310                 __func__, ret);
1311         return -1;
1312     }
1313     mExynosDisplay->mMaxAverageLuminance = (float)max_avg_luminance / DISPLAY_LUMINANCE_UNIT;
1314 
1315     std::tie(ret, min_luminance) = prop_min_luminance.value();
1316     if (ret < 0) {
1317         HWC_LOGE(mExynosDisplay, "%s:: there is no min_luminance (ret = %d)",
1318                 __func__, ret);
1319         return -1;
1320     }
1321     mExynosDisplay->mMinLuminance = (float)min_luminance / DISPLAY_LUMINANCE_UNIT;
1322 
1323     std::tie(ret, hdr_formats) = prop_hdr_formats.value();
1324     if (ret < 0) {
1325         HWC_LOGE(mExynosDisplay, "%s:: there is no hdr_formats (ret = %d)",
1326                 __func__, ret);
1327         return -1;
1328     }
1329 
1330     uint32_t typeBit;
1331     std::tie(typeBit, ret) = prop_hdr_formats.GetEnumValueWithName("Dolby Vision");
1332     if ((ret == 0) && (hdr_formats & (1 << typeBit))) {
1333         mExynosDisplay->mHdrTypes.push_back(HAL_HDR_DOLBY_VISION);
1334         HDEBUGLOGD(eDebugHWC, "%s: supported hdr types : %d",
1335                 mExynosDisplay->mDisplayName.string(), HAL_HDR_DOLBY_VISION);
1336     }
1337     std::tie(typeBit, ret) = prop_hdr_formats.GetEnumValueWithName("HDR10");
1338     if ((ret == 0) && (hdr_formats & (1 << typeBit))) {
1339         mExynosDisplay->mHdrTypes.push_back(HAL_HDR_HDR10);
1340         if (mExynosDisplay->mDevice->mResourceManager->hasHDR10PlusMPP()) {
1341             mExynosDisplay->mHdrTypes.push_back(HAL_HDR_HDR10_PLUS);
1342         }
1343         HDEBUGLOGD(eDebugHWC, "%s: supported hdr types : %d",
1344                 mExynosDisplay->mDisplayName.string(), HAL_HDR_HDR10);
1345     }
1346     std::tie(typeBit, ret) = prop_hdr_formats.GetEnumValueWithName("HLG");
1347     if ((ret == 0) && (hdr_formats & (1 << typeBit))) {
1348         mExynosDisplay->mHdrTypes.push_back(HAL_HDR_HLG);
1349         HDEBUGLOGD(eDebugHWC, "%s: supported hdr types : %d",
1350                 mExynosDisplay->mDisplayName.string(), HAL_HDR_HLG);
1351     }
1352 
1353     ALOGI("%s: get hdrCapabilities info max_luminance(%" PRId64 "), "
1354             "max_avg_luminance(%" PRId64 "), min_luminance(%" PRId64 "), "
1355             "hdr_formats(0x%" PRIx64 ")",
1356             mExynosDisplay->mDisplayName.string(),
1357             max_luminance, max_avg_luminance, min_luminance, hdr_formats);
1358 
1359     ALOGI("%s: mHdrTypes size(%zu), maxLuminance(%f), maxAverageLuminance(%f), minLuminance(%f)",
1360             mExynosDisplay->mDisplayName.string(), mExynosDisplay->mHdrTypes.size(), mExynosDisplay->mMaxLuminance,
1361             mExynosDisplay->mMaxAverageLuminance, mExynosDisplay->mMinLuminance);
1362 
1363     return 0;
1364 }
1365 
getDeconChannel(ExynosMPP * otfMPP)1366 int ExynosDisplayDrmInterface::getDeconChannel(ExynosMPP *otfMPP)
1367 {
1368     int32_t channelNum = sizeof(IDMA_CHANNEL_MAP)/sizeof(dpp_channel_map_t);
1369     for (int i = 0; i < channelNum; i++) {
1370         if((IDMA_CHANNEL_MAP[i].type == otfMPP->mPhysicalType) &&
1371            (IDMA_CHANNEL_MAP[i].index == otfMPP->mPhysicalIndex))
1372             return IDMA_CHANNEL_MAP[i].channel;
1373     }
1374     return -EINVAL;
1375 }
1376 
setupCommitFromDisplayConfig(ExynosDisplayDrmInterface::DrmModeAtomicReq & drmReq,const exynos_win_config_data & config,const uint32_t configIndex,const std::unique_ptr<DrmPlane> & plane,uint32_t & fbId)1377 int32_t ExynosDisplayDrmInterface::setupCommitFromDisplayConfig(
1378         ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq,
1379         const exynos_win_config_data &config,
1380         const uint32_t configIndex,
1381         const std::unique_ptr<DrmPlane> &plane,
1382         uint32_t &fbId)
1383 {
1384     int ret = NO_ERROR;
1385 
1386     if (fbId == 0) {
1387         if ((ret = mFBManager.getBuffer(config, fbId)) < 0) {
1388             HWC_LOGE(mExynosDisplay, "%s:: Failed to get FB, fbId(%d), ret(%d)", __func__, fbId,
1389                      ret);
1390             return ret;
1391         }
1392     }
1393 
1394     if ((ret = drmReq.atomicAddProperty(plane->id(),
1395                 plane->crtc_property(), mDrmCrtc->id())) < 0)
1396         return ret;
1397     if ((ret = drmReq.atomicAddProperty(plane->id(),
1398                     plane->fb_property(), fbId)) < 0)
1399         return ret;
1400     if ((ret = drmReq.atomicAddProperty(plane->id(),
1401                     plane->crtc_x_property(), config.dst.x)) < 0)
1402         return ret;
1403     if ((ret = drmReq.atomicAddProperty(plane->id(),
1404                     plane->crtc_y_property(), config.dst.y)) < 0)
1405         return ret;
1406     if ((ret = drmReq.atomicAddProperty(plane->id(),
1407                     plane->crtc_w_property(), config.dst.w)) < 0)
1408         return ret;
1409     if ((ret = drmReq.atomicAddProperty(plane->id(),
1410                     plane->crtc_h_property(), config.dst.h)) < 0)
1411         return ret;
1412     if ((ret = drmReq.atomicAddProperty(plane->id(),
1413                     plane->src_x_property(), (int)(config.src.x) << 16)) < 0)
1414         return ret;
1415     if ((ret = drmReq.atomicAddProperty(plane->id(),
1416                     plane->src_y_property(), (int)(config.src.y) << 16)) < 0)
1417         HWC_LOGE(mExynosDisplay, "%s:: Failed to add src_y property to plane",
1418                 __func__);
1419     if ((ret = drmReq.atomicAddProperty(plane->id(),
1420                     plane->src_w_property(), (int)(config.src.w) << 16)) < 0)
1421         return ret;
1422     if ((ret = drmReq.atomicAddProperty(plane->id(),
1423                     plane->src_h_property(), (int)(config.src.h) << 16)) < 0)
1424         return ret;
1425 
1426     if ((ret = drmReq.atomicAddProperty(plane->id(),
1427             plane->rotation_property(),
1428             halTransformToDrmRot(config.transform), true)) < 0)
1429         return ret;
1430 
1431     uint64_t drmEnum = 0;
1432     std::tie(drmEnum, ret) = DrmEnumParser::halToDrmEnum(config.blending, mBlendEnums);
1433     if (ret < 0) {
1434         HWC_LOGE(mExynosDisplay, "Fail to convert blend(%d)", config.blending);
1435         return ret;
1436     }
1437     if ((ret = drmReq.atomicAddProperty(plane->id(),
1438                     plane->blend_property(), drmEnum, true)) < 0)
1439         return ret;
1440 
1441     if (plane->zpos_property().id() &&
1442         !plane->zpos_property().is_immutable()) {
1443         uint64_t min_zpos = 0;
1444 
1445         // Ignore ret and use min_zpos as 0 by default
1446         std::tie(std::ignore, min_zpos) = plane->zpos_property().range_min();
1447 
1448         if ((ret = drmReq.atomicAddProperty(plane->id(),
1449                 plane->zpos_property(), configIndex + min_zpos)) < 0)
1450             return ret;
1451     }
1452 
1453     if (plane->alpha_property().id()) {
1454         uint64_t min_alpha = 0;
1455         uint64_t max_alpha = 0;
1456         std::tie(std::ignore, min_alpha) = plane->alpha_property().range_min();
1457         std::tie(std::ignore, max_alpha) = plane->alpha_property().range_max();
1458         if ((ret = drmReq.atomicAddProperty(plane->id(),
1459                 plane->alpha_property(),
1460                 (uint64_t)(((max_alpha - min_alpha) * config.plane_alpha) + 0.5) + min_alpha, true)) < 0)
1461             return ret;
1462     }
1463 
1464     if (config.acq_fence >= 0) {
1465         if ((ret = drmReq.atomicAddProperty(plane->id(),
1466                         plane->in_fence_fd_property(), config.acq_fence)) < 0)
1467             return ret;
1468     }
1469 
1470     if (config.state == config.WIN_STATE_COLOR)
1471     {
1472         if (plane->colormap_property().id()) {
1473             if ((ret = drmReq.atomicAddProperty(plane->id(),
1474                             plane->colormap_property(), config.color)) < 0)
1475                 return ret;
1476         } else {
1477             HWC_LOGE(mExynosDisplay, "colormap property is not supported");
1478         }
1479     }
1480 
1481     std::tie(drmEnum, ret) = DrmEnumParser::halToDrmEnum(
1482                     config.dataspace & HAL_DATASPACE_STANDARD_MASK, mStandardEnums);
1483     if (ret < 0) {
1484         HWC_LOGE(mExynosDisplay, "Fail to convert standard(%d)",
1485                 config.dataspace & HAL_DATASPACE_STANDARD_MASK);
1486         return ret;
1487     }
1488     if ((ret = drmReq.atomicAddProperty(plane->id(),
1489                     plane->standard_property(),
1490                     drmEnum, true)) < 0)
1491         return ret;
1492 
1493     std::tie(drmEnum, ret) = DrmEnumParser::halToDrmEnum(
1494                     config.dataspace & HAL_DATASPACE_TRANSFER_MASK, mTransferEnums);
1495     if (ret < 0) {
1496         HWC_LOGE(mExynosDisplay, "Fail to convert transfer(%d)",
1497                 config.dataspace & HAL_DATASPACE_TRANSFER_MASK);
1498         return ret;
1499     }
1500     if ((ret = drmReq.atomicAddProperty(plane->id(),
1501                     plane->transfer_property(), drmEnum, true)) < 0)
1502         return ret;
1503 
1504     std::tie(drmEnum, ret) = DrmEnumParser::halToDrmEnum(
1505                      config.dataspace & HAL_DATASPACE_RANGE_MASK, mRangeEnums);
1506     if (ret < 0) {
1507         HWC_LOGE(mExynosDisplay, "Fail to convert range(%d)",
1508                 config.dataspace & HAL_DATASPACE_RANGE_MASK);
1509         return ret;
1510     }
1511     if ((ret = drmReq.atomicAddProperty(plane->id(),
1512                     plane->range_property(), drmEnum, true)) < 0)
1513         return ret;
1514 
1515     if (hasHdrInfo(config.dataspace)) {
1516         if ((ret = drmReq.atomicAddProperty(plane->id(),
1517                 plane->min_luminance_property(), config.min_luminance)) < 0)
1518             return ret;
1519         if ((ret = drmReq.atomicAddProperty(plane->id(),
1520                        plane->max_luminance_property(), config.max_luminance)) < 0)
1521             return ret;
1522     }
1523 
1524     if (config.state == config.WIN_STATE_RCD) {
1525         if (plane->block_property().id()) {
1526             if (mBlockState != config.block_area) {
1527                 uint32_t blobId = 0;
1528                 ret = mDrmDevice->CreatePropertyBlob(&config.block_area, sizeof(config.block_area),
1529                                                      &blobId);
1530                 if (ret || (blobId == 0)) {
1531                     HWC_LOGE(mExynosDisplay, "Failed to create blocking region blob id=%d, ret=%d",
1532                              blobId, ret);
1533                     return ret;
1534                 }
1535 
1536                 mBlockState.mRegion = config.block_area;
1537                 if (mBlockState.mBlobId) {
1538                     drmReq.addOldBlob(mBlockState.mBlobId);
1539                 }
1540                 mBlockState.mBlobId = blobId;
1541             }
1542 
1543             if ((ret = drmReq.atomicAddProperty(plane->id(), plane->block_property(),
1544                                                 mBlockState.mBlobId)) < 0) {
1545                 HWC_LOGE(mExynosDisplay, "Failed to set blocking region property %d", ret);
1546                 return ret;
1547             }
1548         }
1549     }
1550 
1551     return NO_ERROR;
1552 }
1553 
setupPartialRegion(DrmModeAtomicReq & drmReq)1554 int32_t ExynosDisplayDrmInterface::setupPartialRegion(DrmModeAtomicReq &drmReq)
1555 {
1556     if (!mDrmCrtc->partial_region_property().id())
1557         return NO_ERROR;
1558 
1559     int ret = NO_ERROR;
1560 
1561     struct decon_frame &update_region = mExynosDisplay->mDpuData.win_update_region;
1562     struct drm_clip_rect partial_rect = {
1563         static_cast<unsigned short>(update_region.x),
1564         static_cast<unsigned short>(update_region.y),
1565         static_cast<unsigned short>(update_region.x + update_region.w),
1566         static_cast<unsigned short>(update_region.y + update_region.h),
1567     };
1568     if ((mPartialRegionState.blob_id == 0) ||
1569          mPartialRegionState.isUpdated(partial_rect))
1570     {
1571         uint32_t blob_id = 0;
1572         ret = mDrmDevice->CreatePropertyBlob(&partial_rect,
1573                 sizeof(partial_rect),&blob_id);
1574         if (ret || (blob_id == 0)) {
1575             HWC_LOGE(mExynosDisplay, "Failed to create partial region "
1576                     "blob id=%d, ret=%d", blob_id, ret);
1577             return ret;
1578         }
1579 
1580         HDEBUGLOGD(eDebugWindowUpdate,
1581                 "%s: partial region updated [%d, %d, %d, %d] -> [%d, %d, %d, %d] blob(%d)",
1582                 mExynosDisplay->mDisplayName.string(),
1583                 mPartialRegionState.partial_rect.x1,
1584                 mPartialRegionState.partial_rect.y1,
1585                 mPartialRegionState.partial_rect.x2,
1586                 mPartialRegionState.partial_rect.y2,
1587                 partial_rect.x1,
1588                 partial_rect.y1,
1589                 partial_rect.x2,
1590                 partial_rect.y2,
1591                 blob_id);
1592         mPartialRegionState.partial_rect = partial_rect;
1593 
1594         if (mPartialRegionState.blob_id)
1595             drmReq.addOldBlob(mPartialRegionState.blob_id);
1596         mPartialRegionState.blob_id = blob_id;
1597     }
1598     if ((ret = drmReq.atomicAddProperty(mDrmCrtc->id(),
1599                     mDrmCrtc->partial_region_property(),
1600                     mPartialRegionState.blob_id)) < 0) {
1601         HWC_LOGE(mExynosDisplay, "Failed to set partial region property %d", ret);
1602         return ret;
1603     }
1604 
1605     return ret;
1606 }
1607 
waitVBlank()1608 int32_t ExynosDisplayDrmInterface::waitVBlank() {
1609     drmVBlank vblank;
1610     uint32_t high_crtc = (mDrmCrtc->pipe() << DRM_VBLANK_HIGH_CRTC_SHIFT);
1611     memset(&vblank, 0, sizeof(vblank));
1612     vblank.request.type = (drmVBlankSeqType)(
1613         DRM_VBLANK_RELATIVE | (high_crtc & DRM_VBLANK_HIGH_CRTC_MASK));
1614     vblank.request.sequence = 1;
1615 
1616     int ret = drmWaitVBlank(mDrmDevice->fd(), &vblank);
1617     return ret;
1618 }
1619 
updateColorSettings(DrmModeAtomicReq & drmReq,uint64_t dqeEnabled)1620 int32_t ExynosDisplayDrmInterface::updateColorSettings(DrmModeAtomicReq &drmReq, uint64_t dqeEnabled) {
1621     int ret = NO_ERROR;
1622 
1623     if (dqeEnabled) {
1624         if ((ret = setDisplayColorSetting(drmReq)) != 0) {
1625             HWC_LOGE(mExynosDisplay, "Failed to set display color setting");
1626             return ret;
1627         }
1628     }
1629 
1630     for (size_t i = 0; i < mExynosDisplay->mDpuData.configs.size(); i++) {
1631         exynos_win_config_data& config = mExynosDisplay->mDpuData.configs[i];
1632         if ((config.state == config.WIN_STATE_BUFFER) ||
1633             (config.state == config.WIN_STATE_COLOR)) {
1634             int channelId = 0;
1635             if ((channelId = getDeconChannel(config.assignedMPP)) < 0) {
1636                 HWC_LOGE(mExynosDisplay, "%s:: Failed to get channel id (%d)",
1637                         __func__, channelId);
1638                 ret = -EINVAL;
1639                 return ret;
1640             }
1641 
1642             auto &plane = mDrmDevice->planes().at(channelId);
1643             uint32_t solidColor = config.color;
1644             if ((ret = setPlaneColorSetting(drmReq, plane, config, solidColor)) != 0) {
1645                 HWC_LOGE(mExynosDisplay, "Failed to set plane color setting, config[%zu]", i);
1646                 return ret;
1647             }
1648             if (config.state == config.WIN_STATE_COLOR && solidColor != config.color) {
1649                 config.color = solidColor;
1650             }
1651         }
1652     }
1653 
1654     return ret;
1655 }
1656 
deliverWinConfigData()1657 int32_t ExynosDisplayDrmInterface::deliverWinConfigData()
1658 {
1659     int ret = NO_ERROR;
1660     DrmModeAtomicReq drmReq(this);
1661     std::unordered_map<uint32_t, uint32_t> planeEnableInfo;
1662     android::String8 result;
1663     bool hasSecureFrameBuffer = false;
1664 
1665     mFrameCounter++;
1666     funcReturnCallback retCallback([&]() {
1667         if ((ret == NO_ERROR) && !drmReq.getError()) {
1668             mFBManager.flip(hasSecureFrameBuffer);
1669         } else if (ret == -ENOMEM) {
1670             mFBManager.releaseAll();
1671         }
1672     });
1673 
1674     mFBManager.checkShrink();
1675 
1676     bool needModesetForReadback = false;
1677     if (mExynosDisplay->mDpuData.enable_readback) {
1678         if ((ret = setupWritebackCommit(drmReq)) < 0) {
1679             HWC_LOGE(mExynosDisplay, "%s:: Failed to setup writeback commit ret(%d)",
1680                     __func__, ret);
1681             return ret;
1682         }
1683         needModesetForReadback = true;
1684     } else {
1685         if (mReadbackInfo.mNeedClearReadbackCommit) {
1686             if ((ret = clearWritebackCommit(drmReq)) < 0) {
1687                 HWC_LOGE(mExynosDisplay, "%s: Failed to clear writeback commit ret(%d)",
1688                          __func__, ret);
1689                 return ret;
1690             }
1691             needModesetForReadback = true;
1692         }
1693     }
1694 
1695     uint64_t mipi_sync_type = 0;
1696     if (mDesiredModeState.needsModeSet()) {
1697         if (mExynosDisplay->checkRrCompensationEnabled()) {
1698             mipi_sync_type |=
1699                 1 << mMipiSyncEnums[toUnderlying(HalMipiSyncType::HAL_MIPI_CMD_SYNC_REFRESH_RATE)];
1700         }
1701 
1702         if ((ret = setDisplayMode(drmReq, mDesiredModeState.blob_id)) < 0) {
1703             HWC_LOGE(mExynosDisplay, "%s: Fail to apply display mode",
1704                     __func__);
1705             return ret;
1706         }
1707     }
1708 
1709     if ((ret = setupPartialRegion(drmReq)) != NO_ERROR)
1710         return ret;
1711 
1712     uint64_t out_fences[mDrmDevice->crtcs().size()];
1713     if ((ret = drmReq.atomicAddProperty(mDrmCrtc->id(),
1714                     mDrmCrtc->out_fence_ptr_property(),
1715                     (uint64_t)&out_fences[mDrmCrtc->pipe()], true)) < 0) {
1716         return ret;
1717     }
1718 
1719     for (auto &plane : mDrmDevice->planes()) {
1720         planeEnableInfo[plane->id()] = 0;
1721     }
1722 
1723     uint64_t dqeEnable = 1;
1724     if (mExynosDisplay->mDpuData.enable_readback &&
1725         !mExynosDisplay->mDpuData.readback_info.requested_from_service) {
1726         dqeEnable = 0;
1727     }
1728 
1729     if ((ret = drmReq.atomicAddProperty(mDrmCrtc->id(),
1730                     mDrmCrtc->dqe_enabled_property(), dqeEnable)) < 0) {
1731         HWC_LOGE(mExynosDisplay, "%s: Fail to dqe_enable setting",
1732                 __func__);
1733         return ret;
1734     }
1735 
1736     // Update of color settings could change layer's solid color. So it should
1737     // be called before use of layer's solid color.
1738     if ((ret = updateColorSettings(drmReq, dqeEnable)) != 0) {
1739         HWC_LOGE(mExynosDisplay, "failed to update color settings (%d)", ret);
1740         return ret;
1741     }
1742 
1743     for (size_t i = 0; i < mExynosDisplay->mDpuData.configs.size(); i++) {
1744         exynos_win_config_data& config = mExynosDisplay->mDpuData.configs[i];
1745         if ((config.state == config.WIN_STATE_BUFFER) ||
1746             (config.state == config.WIN_STATE_COLOR)) {
1747             int channelId = 0;
1748             if ((channelId = getDeconChannel(config.assignedMPP)) < 0) {
1749                 HWC_LOGE(mExynosDisplay, "%s:: Failed to get channel id (%d)",
1750                         __func__, channelId);
1751                 ret = -EINVAL;
1752                 return ret;
1753             }
1754             /* src size should be set even in dim layer */
1755             if (config.state == config.WIN_STATE_COLOR) {
1756                 config.src.w = config.dst.w;
1757                 config.src.h = config.dst.h;
1758             }
1759             auto &plane = mDrmDevice->planes().at(channelId);
1760             uint32_t fbId = 0;
1761             if ((ret = setupCommitFromDisplayConfig(drmReq, config, i, plane, fbId)) < 0) {
1762                 HWC_LOGE(mExynosDisplay, "setupCommitFromDisplayConfig failed, config[%zu]", i);
1763                 return ret;
1764             }
1765             hasSecureFrameBuffer |= (isFramebuffer(config.layer) && config.protection);
1766             /* Set this plane is enabled */
1767             planeEnableInfo[plane->id()] = 1;
1768         }
1769     }
1770 
1771     for (size_t i = 0; i < mExynosDisplay->mDpuData.rcdConfigs.size(); ++i) {
1772         exynos_win_config_data &config = mExynosDisplay->mDpuData.rcdConfigs[i];
1773         if (config.state == config.WIN_STATE_RCD) {
1774             const int channelId = mExynosDisplay->mDevice->getSpecialPlaneId(
1775                     mExynosDisplay->mIndex); // TODO: b/227584297
1776             auto &plane = mDrmDevice->planes().at(channelId);
1777             uint32_t fbId = 0;
1778             if ((ret = setupCommitFromDisplayConfig(drmReq, config, i, plane, fbId)) < 0) {
1779                 HWC_LOGE(mExynosDisplay, "setupCommitFromDisplayConfig failed, config[%zu]", i);
1780             }
1781             planeEnableInfo[plane->id()] = 1;
1782         }
1783     }
1784 
1785     /* Disable unused plane */
1786     for (auto &plane : mDrmDevice->planes()) {
1787         if (planeEnableInfo[plane->id()] == 0) {
1788             /* Don't disable planes that are reserved to other display */
1789             ExynosMPP* exynosMPP = mExynosMPPsForPlane[plane->id()];
1790             if ((exynosMPP != NULL) && (mExynosDisplay != NULL) &&
1791                 (exynosMPP->mAssignedState & MPP_ASSIGN_STATE_RESERVED) &&
1792                 (exynosMPP->mReservedDisplay != (int32_t)mExynosDisplay->mDisplayId))
1793                 continue;
1794 
1795             if ((ret = drmReq.atomicAddProperty(plane->id(),
1796                     plane->crtc_property(), 0)) < 0)
1797                 return ret;
1798 
1799             if ((ret = drmReq.atomicAddProperty(plane->id(),
1800                     plane->fb_property(), 0)) < 0)
1801                 return ret;
1802         }
1803     }
1804 
1805     if (ATRACE_ENABLED()) {
1806         mExynosDisplay->traceLayerTypes();
1807     }
1808 
1809     if (mExynosDisplay->mBrightnessController) {
1810         bool ghbmSync, lhbmSync, blSync;
1811         bool mixedComposition = mExynosDisplay->isMixedComposition()
1812                                 || mExynosDisplay->isPriorFrameMixedCompostion();
1813         ret = mExynosDisplay->mBrightnessController->prepareFrameCommit(*mExynosDisplay,
1814                                         *mDrmConnector, drmReq, mixedComposition,
1815                                         ghbmSync, lhbmSync, blSync);
1816         if (ret < 0) {
1817             HWC_LOGE(mExynosDisplay, "%s: Fail to config brightness", __func__);
1818         } else {
1819             if (ghbmSync) {
1820                 mipi_sync_type |=
1821                     1 << mMipiSyncEnums[toUnderlying(HalMipiSyncType::HAL_MIPI_CMD_SYNC_GHBM)];
1822             }
1823             if (lhbmSync) {
1824                 mipi_sync_type |=
1825                     1 << mMipiSyncEnums[toUnderlying(HalMipiSyncType::HAL_MIPI_CMD_SYNC_LHBM)];
1826             }
1827             if (blSync) {
1828                 mipi_sync_type |=
1829                     1 << mMipiSyncEnums[toUnderlying(HalMipiSyncType::HAL_MIPI_CMD_SYNC_BL)];
1830             }
1831         }
1832     }
1833 
1834     uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK;
1835     if (needModesetForReadback || !mDesiredModeState.isSeamless())
1836         flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
1837 
1838     /* For Histogram */
1839     if (dqeEnable && (ret = setDisplayHistogramSetting(drmReq)) != 0) {
1840         HWC_LOGE(mExynosDisplay, "Failed to set display histogram setting (%d)", ret);
1841         return ret;
1842     }
1843 
1844     if (mDrmConnector->mipi_sync().id() && (mipi_sync_type != 0)) {
1845         // skip mipi sync in Doze mode
1846         bool inDoze = isDozeModeAvailable() && mDozeDrmMode.id() == mActiveModeState.mode.id();
1847         if (!inDoze) {
1848             ATRACE_NAME("mipi_sync"); // mark this commit
1849             if ((ret = drmReq.atomicAddProperty(mDrmConnector->id(),
1850                                                 mDrmConnector->mipi_sync(),
1851                                                 mipi_sync_type)) < 0) {
1852                 HWC_LOGE(mExynosDisplay, "%s: Fail to set mipi_sync property (%d)", __func__, ret);
1853             }
1854         }
1855     }
1856 
1857     auto expectedPresentTime = mExynosDisplay->getPendingExpectedPresentTime();
1858     if (expectedPresentTime != 0) {
1859         /* TODO: don't pass expected present time before we can provide accurate time that desire
1860          * refresh rate take effect (b/202346402)
1861          */
1862         if (!mVsyncCallback.getDesiredVsyncPeriod()) {
1863             if ((ret = drmReq.atomicAddProperty(mDrmCrtc->id(),
1864                                                 mDrmCrtc->expected_present_time_property(),
1865                                                 expectedPresentTime)) < 0) {
1866                 HWC_LOGE(mExynosDisplay, "%s: Fail to set expected_present_time property (%d)",
1867                          __func__, ret);
1868             }
1869         }
1870         mExynosDisplay->applyExpectedPresentTime();
1871     }
1872 
1873     if ((ret = drmReq.commit(flags, true)) < 0) {
1874         HWC_LOGE(mExynosDisplay, "%s:: Failed to commit pset ret=%d in deliverWinConfigData()\n",
1875                 __func__, ret);
1876         return ret;
1877     }
1878 
1879     mExynosDisplay->mDpuData.retire_fence = (int)out_fences[mDrmCrtc->pipe()];
1880     /*
1881      * [HACK] dup retire_fence for each layer's release fence
1882      * Do not use hwc_dup because hwc_dup increase usage count of fence treacer
1883      * Usage count of this fence is incresed by ExynosDisplay::deliverWinConfigData()
1884      */
1885     for (auto &display_config : mExynosDisplay->mDpuData.configs) {
1886         if ((display_config.state == display_config.WIN_STATE_BUFFER) ||
1887             (display_config.state == display_config.WIN_STATE_CURSOR)) {
1888             display_config.rel_fence =
1889                 dup((int)out_fences[mDrmCrtc->pipe()]);
1890         }
1891     }
1892 
1893     if (mDesiredModeState.needsModeSet()) {
1894         mDesiredModeState.apply(mActiveModeState, drmReq);
1895         if (!mActiveModeState.isSeamless()) {
1896             mDrmConnector->ResetLpMode();
1897             getLowPowerDrmModeModeInfo();
1898         }
1899         mVsyncCallback.setDesiredVsyncPeriod(
1900                 nsecsPerSec/mActiveModeState.mode.v_refresh());
1901         /* Enable vsync to check vsync period */
1902         mDrmVSyncWorker.VSyncControl(true);
1903     }
1904 
1905     return NO_ERROR;
1906 }
1907 
clearDisplayMode(DrmModeAtomicReq & drmReq)1908 int32_t ExynosDisplayDrmInterface::clearDisplayMode(DrmModeAtomicReq &drmReq)
1909 {
1910     int ret = NO_ERROR;
1911 
1912     if ((ret = drmReq.atomicAddProperty(mDrmConnector->id(),
1913             mDrmConnector->crtc_id_property(), 0)) < 0)
1914         return ret;
1915 
1916     if ((ret = drmReq.atomicAddProperty(mDrmCrtc->id(),
1917             mDrmCrtc->mode_property(), 0)) < 0)
1918         return ret;
1919 
1920     if ((ret = drmReq.atomicAddProperty(mDrmCrtc->id(),
1921            mDrmCrtc->active_property(), 0)) < 0)
1922         return ret;
1923 
1924     return NO_ERROR;
1925 }
1926 
clearDisplayPlanes(DrmModeAtomicReq & drmReq)1927 int32_t ExynosDisplayDrmInterface::clearDisplayPlanes(DrmModeAtomicReq &drmReq)
1928 {
1929     int ret = NO_ERROR;
1930 
1931     /* Disable all planes */
1932     for (auto &plane : mDrmDevice->planes()) {
1933         /* Do not disable planes that are reserved to other dispaly */
1934         ExynosMPP* exynosMPP = mExynosMPPsForPlane[plane->id()];
1935         if ((exynosMPP != NULL) && (mExynosDisplay != NULL) &&
1936             (exynosMPP->mAssignedState & MPP_ASSIGN_STATE_RESERVED) &&
1937             (exynosMPP->mReservedDisplay != (int32_t)mExynosDisplay->mDisplayId))
1938             continue;
1939 
1940         if ((ret = drmReq.atomicAddProperty(plane->id(),
1941                                             plane->crtc_property(), 0)) < 0) {
1942             break;
1943         }
1944 
1945         if ((ret = drmReq.atomicAddProperty(plane->id(),
1946                                             plane->fb_property(), 0)) < 0) {
1947             break;
1948         }
1949     }
1950 
1951     return ret;
1952 }
1953 
clearDisplay(bool needModeClear)1954 int32_t ExynosDisplayDrmInterface::clearDisplay(bool needModeClear)
1955 {
1956     ExynosDevice *exynosDevice = mExynosDisplay->mDevice;
1957     const bool isAsyncOff = needModeClear && exynosDevice->isDispOffAsyncSupported();
1958     int ret = NO_ERROR;
1959     DrmModeAtomicReq drmReq(this);
1960 
1961     ret = clearDisplayPlanes(drmReq);
1962     if (ret != NO_ERROR) {
1963         HWC_LOGE(mExynosDisplay, "%s: Failed to clear planes", __func__);
1964 
1965         return ret;
1966     }
1967 
1968     /* Disable readback connector if required */
1969     if (mReadbackInfo.mNeedClearReadbackCommit &&
1970         !mExynosDisplay->mDpuData.enable_readback) {
1971         if ((ret = clearWritebackCommit(drmReq)) < 0) {
1972             HWC_LOGE(mExynosDisplay, "%s: Failed to apply writeback", __func__);
1973             return ret;
1974         }
1975     }
1976 
1977     /* Disable ModeSet */
1978     if (needModeClear && !isAsyncOff) {
1979         if ((ret = clearDisplayMode(drmReq)) < 0) {
1980             HWC_LOGE(mExynosDisplay, "%s: Failed to apply display mode", __func__);
1981             return ret;
1982         }
1983     }
1984 
1985     ret = drmReq.commit(DRM_MODE_ATOMIC_ALLOW_MODESET, true);
1986     if (ret) {
1987         HWC_LOGE(mExynosDisplay, "%s:: Failed to commit pset ret=%d in clearDisplay()\n",
1988                 __func__, ret);
1989         return ret;
1990     }
1991 
1992     /* During async off we're clearing planes within a single refresh cycle
1993      * and then offloading display off asynchronously.
1994      */
1995     if (isAsyncOff) {
1996         if ((ret = clearDisplayMode(drmReq)) < 0) {
1997             HWC_LOGE(mExynosDisplay, "%s: Failed to apply display mode", __func__);
1998             return ret;
1999         }
2000 
2001         ret = drmReq.commit(DRM_MODE_ATOMIC_ALLOW_MODESET | DRM_MODE_ATOMIC_NONBLOCK, true);
2002         if (ret) {
2003             HWC_LOGE(mExynosDisplay, "%s:: Failed to commit pset ret=%d in clearDisplay()\n",
2004                      __func__, ret);
2005             return ret;
2006         }
2007     }
2008 
2009     if (needModeClear) mActiveModeState.forceModeSet();
2010 
2011     return NO_ERROR;
2012 }
2013 
disableSelfRefresh(uint32_t disable)2014 int32_t ExynosDisplayDrmInterface::disableSelfRefresh(uint32_t disable)
2015 {
2016     return 0;
2017 }
2018 
setForcePanic()2019 int32_t ExynosDisplayDrmInterface::setForcePanic()
2020 {
2021     if (exynosHWCControl.forcePanic == 0)
2022         return NO_ERROR;
2023 
2024     usleep(20000000);
2025 
2026     FILE *forcePanicFd = fopen(HWC_FORCE_PANIC_PATH, "w");
2027     if (forcePanicFd == NULL) {
2028         ALOGW("%s:: Failed to open fd", __func__);
2029         return -1;
2030     }
2031 
2032     int val = 1;
2033     fwrite(&val, sizeof(int), 1, forcePanicFd);
2034     fclose(forcePanicFd);
2035 
2036     return 0;
2037 }
2038 
DrmModeAtomicReq(ExynosDisplayDrmInterface * displayInterface)2039 ExynosDisplayDrmInterface::DrmModeAtomicReq::DrmModeAtomicReq(ExynosDisplayDrmInterface *displayInterface)
2040     : mDrmDisplayInterface(displayInterface)
2041 {
2042     mPset = drmModeAtomicAlloc();
2043     mSavedPset = NULL;
2044 }
2045 
~DrmModeAtomicReq()2046 ExynosDisplayDrmInterface::DrmModeAtomicReq::~DrmModeAtomicReq()
2047 {
2048     if (mError != 0) {
2049         android::String8 result;
2050         result.appendFormat("atomic commit error\n");
2051         if (hwcCheckDebugMessages(eDebugDisplayInterfaceConfig) == false)
2052             dumpAtomicCommitInfo(result);
2053         HWC_LOGE(mDrmDisplayInterface->mExynosDisplay, "%s", result.string());
2054     }
2055 
2056     if(mPset)
2057         drmModeAtomicFree(mPset);
2058 
2059     if (destroyOldBlobs() != NO_ERROR)
2060         HWC_LOGE(mDrmDisplayInterface->mExynosDisplay, "destroy blob error");
2061 }
2062 
atomicAddProperty(const uint32_t id,const DrmProperty & property,uint64_t value,bool optional)2063 int32_t ExynosDisplayDrmInterface::DrmModeAtomicReq::atomicAddProperty(
2064         const uint32_t id,
2065         const DrmProperty &property,
2066         uint64_t value, bool optional)
2067 {
2068     if (!optional && !property.id()) {
2069         HWC_LOGE(mDrmDisplayInterface->mExynosDisplay, "%s:: %s property id(%d) for id(%d) is not available",
2070                 __func__, property.name().c_str(), property.id(), id);
2071         return -EINVAL;
2072     }
2073 
2074     if (property.id()) {
2075         int ret = drmModeAtomicAddProperty(mPset, id,
2076                 property.id(), value);
2077         if (ret < 0) {
2078             HWC_LOGE(mDrmDisplayInterface->mExynosDisplay, "%s:: Failed to add property %d(%s) for id(%d), ret(%d)",
2079                     __func__, property.id(), property.name().c_str(), id, ret);
2080             return ret;
2081         }
2082     }
2083 
2084     return NO_ERROR;
2085 }
2086 
dumpAtomicCommitInfo(String8 & result,bool debugPrint)2087 String8& ExynosDisplayDrmInterface::DrmModeAtomicReq::dumpAtomicCommitInfo(
2088         String8 &result, bool debugPrint)
2089 {
2090     /* print log only if eDebugDisplayInterfaceConfig flag is set when debugPrint is true */
2091     if (debugPrint &&
2092         (hwcCheckDebugMessages(eDebugDisplayInterfaceConfig) == false))
2093         return result;
2094 
2095     if (debugPrint)
2096         ALOGD("%s atomic config ++++++++++++", mDrmDisplayInterface->mExynosDisplay->mDisplayName.string());
2097 
2098     for (int i = 0; i < drmModeAtomicGetCursor(mPset); i++) {
2099         const DrmProperty *property = NULL;
2100         String8 objectName;
2101         /* Check crtc properties */
2102         if (mPset->items[i].object_id == mDrmDisplayInterface->mDrmCrtc->id()) {
2103             for (auto property_ptr : mDrmDisplayInterface->mDrmCrtc->properties()) {
2104                 if (mPset->items[i].property_id == property_ptr->id()){
2105                     property = property_ptr;
2106                     objectName.appendFormat("Crtc");
2107                     break;
2108                 }
2109             }
2110             if (property == NULL) {
2111                 HWC_LOGE(mDrmDisplayInterface->mExynosDisplay,
2112                         "%s:: object id is crtc but there is no matched property",
2113                         __func__);
2114             }
2115         } else if (mPset->items[i].object_id == mDrmDisplayInterface->mDrmConnector->id()) {
2116             for (auto property_ptr : mDrmDisplayInterface->mDrmConnector->properties()) {
2117                 if (mPset->items[i].property_id == property_ptr->id()){
2118                     property = property_ptr;
2119                     objectName.appendFormat("Connector");
2120                     break;
2121                 }
2122             }
2123             if (property == NULL) {
2124                 HWC_LOGE(mDrmDisplayInterface->mExynosDisplay,
2125                         "%s:: object id is connector but there is no matched property",
2126                         __func__);
2127             }
2128         } else {
2129             uint32_t channelId = 0;
2130             for (auto &plane : mDrmDisplayInterface->mDrmDevice->planes()) {
2131                 if (mPset->items[i].object_id == plane->id()) {
2132                     for (auto property_ptr : plane->properties()) {
2133                         if (mPset->items[i].property_id == property_ptr->id()){
2134                             property = property_ptr;
2135                             objectName.appendFormat("Plane[%d]", channelId);
2136                             break;
2137                         }
2138                     }
2139                     if (property == NULL) {
2140                         HWC_LOGE(mDrmDisplayInterface->mExynosDisplay,
2141                                 "%s:: object id is plane but there is no matched property",
2142                                 __func__);
2143                     }
2144                 }
2145                 channelId++;
2146             }
2147         }
2148         if (property == NULL) {
2149             HWC_LOGE(mDrmDisplayInterface->mExynosDisplay,
2150                     "%s:: Fail to get property[%d] (object_id: %d, property_id: %d, value: %" PRId64 ")",
2151                     __func__, i, mPset->items[i].object_id, mPset->items[i].property_id,
2152                     mPset->items[i].value);
2153             continue;
2154         }
2155 
2156         if (debugPrint)
2157             ALOGD("property[%d] %s object_id: %d, property_id: %d, name: %s,  value: %" PRId64 ")\n",
2158                     i, objectName.string(), mPset->items[i].object_id, mPset->items[i].property_id, property->name().c_str(), mPset->items[i].value);
2159         else
2160             result.appendFormat("property[%d] %s object_id: %d, property_id: %d, name: %s,  value: %" PRId64 ")\n",
2161                 i,  objectName.string(), mPset->items[i].object_id, mPset->items[i].property_id, property->name().c_str(), mPset->items[i].value);
2162     }
2163     return result;
2164 }
2165 
commit(uint32_t flags,bool loggingForDebug)2166 int ExynosDisplayDrmInterface::DrmModeAtomicReq::commit(uint32_t flags, bool loggingForDebug)
2167 {
2168     ATRACE_NAME("drmModeAtomicCommit");
2169     android::String8 result;
2170 
2171     /*
2172      * During kernel is in TUI, all atomic commits should be returned with error EPERM(-1).
2173      * To avoid handling atomic commit as fail, it needs to check TUI status.
2174      */
2175     int ret = drmModeAtomicCommit(mDrmDisplayInterface->mDrmDevice->fd(),
2176             mPset, flags, mDrmDisplayInterface->mDrmDevice);
2177     if (loggingForDebug)
2178         dumpAtomicCommitInfo(result, true);
2179     if ((ret == -EPERM) && mDrmDisplayInterface->mDrmDevice->event_listener()->IsDrmInTUI()) {
2180         ALOGV("skip atomic commit error handling as kernel is in TUI");
2181         ret = NO_ERROR;
2182     } else if (ret < 0) {
2183         HWC_LOGE(mDrmDisplayInterface->mExynosDisplay, "commit error: %d", ret);
2184         setError(ret);
2185     }
2186 
2187     return ret;
2188 }
2189 
getReadbackBufferAttributes(int32_t * outFormat,int32_t * outDataspace)2190 int32_t ExynosDisplayDrmInterface::getReadbackBufferAttributes(
2191         int32_t* /*android_pixel_format_t*/ outFormat,
2192         int32_t* /*android_dataspace_t*/ outDataspace)
2193 {
2194     DrmConnector *writeback_conn = mReadbackInfo.getWritebackConnector();
2195     if (writeback_conn == NULL) {
2196         ALOGE("%s: There is no writeback connection", __func__);
2197         return -EINVAL;
2198     }
2199     mReadbackInfo.pickFormatDataspace();
2200     if (mReadbackInfo.mReadbackFormat ==
2201             HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
2202         ALOGE("readback format(%d) is not valid",
2203                 mReadbackInfo.mReadbackFormat);
2204         return -EINVAL;
2205     }
2206     *outFormat = mReadbackInfo.mReadbackFormat;
2207     *outDataspace = HAL_DATASPACE_UNKNOWN;
2208     return NO_ERROR;
2209 }
2210 
setupWritebackCommit(DrmModeAtomicReq & drmReq)2211 int32_t ExynosDisplayDrmInterface::setupWritebackCommit(DrmModeAtomicReq &drmReq)
2212 {
2213     int ret = NO_ERROR;
2214     DrmConnector *writeback_conn = mReadbackInfo.getWritebackConnector();
2215     if (writeback_conn == NULL) {
2216         ALOGE("%s: There is no writeback connection", __func__);
2217         return -EINVAL;
2218     }
2219     if (writeback_conn->writeback_fb_id().id() == 0 ||
2220         writeback_conn->writeback_out_fence().id() == 0) {
2221         ALOGE("%s: Writeback properties don't exit", __func__);
2222         return -EINVAL;
2223     }
2224 
2225     uint32_t writeback_fb_id = 0;
2226     exynos_win_config_data writeback_config;
2227     VendorGraphicBufferMeta gmeta(mExynosDisplay->mDpuData.readback_info.handle);
2228 
2229     writeback_config.state = exynos_win_config_data::WIN_STATE_BUFFER;
2230     writeback_config.format = mReadbackInfo.mReadbackFormat;
2231     writeback_config.src = {0, 0, mExynosDisplay->mXres, mExynosDisplay->mYres,
2232                             gmeta.stride, gmeta.vstride};
2233     writeback_config.dst = {0, 0, mExynosDisplay->mXres, mExynosDisplay->mYres,
2234                             gmeta.stride, gmeta.vstride};
2235     writeback_config.fd_idma[0] = gmeta.fd;
2236     writeback_config.fd_idma[1] = gmeta.fd1;
2237     writeback_config.fd_idma[2] = gmeta.fd2;
2238     if ((ret = mFBManager.getBuffer(writeback_config, writeback_fb_id)) < 0) {
2239         ALOGE("%s: getBuffer() fail ret(%d)", __func__, ret);
2240         return ret;
2241     }
2242 
2243     if ((ret = drmReq.atomicAddProperty(writeback_conn->id(),
2244             writeback_conn->writeback_fb_id(),
2245             writeback_fb_id)) < 0)
2246         return ret;
2247 
2248     if ((ret = drmReq.atomicAddProperty(writeback_conn->id(),
2249             writeback_conn->writeback_out_fence(),
2250             (uint64_t)& mExynosDisplay->mDpuData.readback_info.acq_fence)) < 0)
2251         return ret;
2252 
2253     if ((ret = drmReq.atomicAddProperty(writeback_conn->id(),
2254             writeback_conn->crtc_id_property(),
2255             mDrmCrtc->id())) < 0)
2256         return ret;
2257 
2258     mReadbackInfo.setFbId(writeback_fb_id);
2259     mReadbackInfo.mNeedClearReadbackCommit = true;
2260     return NO_ERROR;
2261 }
2262 
clearWritebackCommit(DrmModeAtomicReq & drmReq)2263 int32_t ExynosDisplayDrmInterface::clearWritebackCommit(DrmModeAtomicReq &drmReq)
2264 {
2265     int ret;
2266 
2267     DrmConnector *writeback_conn = mReadbackInfo.getWritebackConnector();
2268     if (writeback_conn == NULL) {
2269         ALOGE("%s: There is no writeback connection", __func__);
2270         return -EINVAL;
2271     }
2272 
2273     if ((ret = drmReq.atomicAddProperty(writeback_conn->id(),
2274             writeback_conn->writeback_fb_id(), 0)) < 0)
2275         return ret;
2276 
2277     if ((ret = drmReq.atomicAddProperty(writeback_conn->id(),
2278             writeback_conn->writeback_out_fence(), 0)) < 0)
2279         return ret;
2280 
2281     if ((ret = drmReq.atomicAddProperty(writeback_conn->id(),
2282             writeback_conn->crtc_id_property(), 0)) < 0)
2283         return ret;
2284 
2285     mReadbackInfo.mNeedClearReadbackCommit = false;
2286     return NO_ERROR;
2287 }
2288 
init(DrmDevice * drmDevice,uint32_t displayId)2289 void ExynosDisplayDrmInterface::DrmReadbackInfo::init(DrmDevice *drmDevice, uint32_t displayId)
2290 {
2291     mDrmDevice = drmDevice;
2292     mWritebackConnector = mDrmDevice->AvailableWritebackConnector(displayId);
2293     if (mWritebackConnector == NULL) {
2294         ALOGI("writeback is not supported");
2295         return;
2296     }
2297     if (mWritebackConnector->writeback_fb_id().id() == 0 ||
2298         mWritebackConnector->writeback_out_fence().id() == 0) {
2299         ALOGE("%s: Writeback properties don't exit", __func__);
2300         mWritebackConnector = NULL;
2301         return;
2302     }
2303 
2304     if (mWritebackConnector->writeback_pixel_formats().id()) {
2305         int32_t ret = NO_ERROR;
2306         uint64_t blobId;
2307         std::tie(ret, blobId) = mWritebackConnector->writeback_pixel_formats().value();
2308         if (ret) {
2309             ALOGE("Fail to get blob id for writeback_pixel_formats");
2310             return;
2311         }
2312         drmModePropertyBlobPtr blob = drmModeGetPropertyBlob(mDrmDevice->fd(), blobId);
2313         if (!blob) {
2314             ALOGE("Fail to get blob for writeback_pixel_formats(%" PRId64 ")", blobId);
2315             return;
2316         }
2317         uint32_t formatNum = (blob->length)/sizeof(uint32_t);
2318         uint32_t *formats = (uint32_t *)blob->data;
2319         for (uint32_t i = 0; i < formatNum; i++) {
2320             int halFormat = drmFormatToHalFormat(formats[i]);
2321             ALOGD("supported writeback format[%d] %4.4s, %d", i, (char *)&formats[i], halFormat);
2322             if (halFormat != HAL_PIXEL_FORMAT_EXYNOS_UNDEFINED)
2323                 mSupportedFormats.push_back(halFormat);
2324         }
2325         drmModeFreePropertyBlob(blob);
2326     }
2327 }
2328 
pickFormatDataspace()2329 void ExynosDisplayDrmInterface::DrmReadbackInfo::pickFormatDataspace()
2330 {
2331     if (!mSupportedFormats.empty())
2332         mReadbackFormat = mSupportedFormats[0];
2333     auto it = std::find(mSupportedFormats.begin(),
2334             mSupportedFormats.end(), PREFERRED_READBACK_FORMAT);
2335     if (it != mSupportedFormats.end())
2336         mReadbackFormat = *it;
2337 }
2338 
getDisplayFakeEdid(uint8_t & outPort,uint32_t & outDataSize,uint8_t * outData)2339 int32_t ExynosDisplayDrmInterface::getDisplayFakeEdid(uint8_t &outPort, uint32_t &outDataSize,
2340                                                       uint8_t *outData) {
2341     int width = mExynosDisplay->mXres;
2342     int height = mExynosDisplay->mYres;
2343     int clock = (width) * (height) * 60 / 10000;
2344     std::array<uint8_t, 128> edid_buf{
2345             0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, /* header */
2346             0x1C, 0xEC,                                     /* manufacturer GGL */
2347             0x00, 0x00,                                     /* product */
2348             0x00, 0x00, 0x00, 0x00,                         /* serial number */
2349             0x01,                                           /* week of manufacture */
2350             0x00,                                           /* year of manufacture */
2351             0x01, 0x03,                                     /* EDID version */
2352             0x80,                                           /* capabilities - digital */
2353             0x00,                                           /* horizontal in cm */
2354             0x00,                                           /* vertical in cm */
2355             0x78,                                           /* gamma 2.2 */
2356             0xEE, 0xEE, 0x91, 0xA3, 0x54, 0x4C, 0x99, 0x26, 0x0F, 0x50, 0x54, /* chromaticity */
2357             0x00, 0x00, 0x00, /* no default timings */
2358             /* no standard timings */
2359             0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
2360             0x01, 0x01,
2361             /* descriptor block 1 */
2362             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2363             0x00, 0x00, 0x00, 0x00,
2364             /* descriptor block 2 */
2365             0x00, 0x00, 0x00, 0xFD, 0x00, 0x00, 0xC8, 0x00, 0xC8, 0x64, 0x00, 0x0A, 0x20, 0x20,
2366             0x20, 0x20, 0x20, 0x20,
2367             /* descriptor block 3 */
2368             0x00, 0x00, 0x00, 0xFC, 0x00, 'C', 'o', 'm', 'm', 'o', 'n', ' ', 'P', 'a', 'n', 'e',
2369             'l', '\n',
2370             /* descriptor block 4 */
2371             0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2372             0x00, 0x00, 0x00, 0x00, 0x00, /* number of extensions */
2373             0x00                          /* checksum */
2374     };
2375     edid_buf[55] = clock >> 8;
2376     edid_buf[56] = width & 0xff;
2377     edid_buf[58] = (width >> 4) & 0xf0;
2378     edid_buf[59] = height & 0xff;
2379     edid_buf[61] = (height >> 4) & 0xf0;
2380 
2381     unsigned int sum = std::accumulate(edid_buf.begin(), edid_buf.end() - 1, 0);
2382     edid_buf[127] = (0x100 - (sum & 0xFF)) & 0xFF;
2383     if (outData) {
2384         outDataSize = std::min<uint32_t>(outDataSize, edid_buf.size());
2385         memcpy(outData, edid_buf.data(), outDataSize);
2386     } else {
2387         outDataSize = static_cast<uint32_t>(edid_buf.size());
2388     }
2389 
2390     outPort = mExynosDisplay->mDisplayId;
2391     ALOGD("using Display Fake Edid");
2392     return HWC2_ERROR_NONE;
2393 }
2394 
getDisplayIdentificationData(uint8_t * outPort,uint32_t * outDataSize,uint8_t * outData)2395 int32_t ExynosDisplayDrmInterface::getDisplayIdentificationData(
2396         uint8_t* outPort, uint32_t* outDataSize, uint8_t* outData)
2397 {
2398     if ((mDrmDevice == nullptr) || (mDrmConnector == nullptr)) {
2399         ALOGE("%s: display(%s) mDrmDevice(%p), mDrmConnector(%p)",
2400                 __func__, mExynosDisplay->mDisplayName.string(),
2401                 mDrmDevice, mDrmConnector);
2402         return HWC2_ERROR_UNSUPPORTED;
2403     }
2404 
2405     if (mDrmConnector->edid_property().id() == 0) {
2406         ALOGD("%s: edid_property is not supported",
2407                 mExynosDisplay->mDisplayName.string());
2408         return HWC2_ERROR_UNSUPPORTED;
2409     }
2410 
2411     if (outPort == nullptr || outDataSize == nullptr) return HWC2_ERROR_BAD_PARAMETER;
2412 
2413     drmModePropertyBlobPtr blob;
2414     int ret;
2415     uint64_t blobId;
2416 
2417     std::tie(ret, blobId) = mDrmConnector->edid_property().value();
2418     if (ret) {
2419         ALOGE("Failed to get edid property value.");
2420         return HWC2_ERROR_UNSUPPORTED;
2421     }
2422     if (blobId == 0) {
2423         ALOGD("%s: edid_property is supported but blob is not valid",
2424                 mExynosDisplay->mDisplayName.string());
2425         return getDisplayFakeEdid(*outPort, *outDataSize, outData);
2426     }
2427 
2428     blob = drmModeGetPropertyBlob(mDrmDevice->fd(), blobId);
2429     if (blob == nullptr) {
2430         ALOGD("%s: Failed to get blob",
2431                 mExynosDisplay->mDisplayName.string());
2432         return HWC2_ERROR_UNSUPPORTED;
2433     }
2434 
2435     if (outData) {
2436         *outDataSize = std::min(*outDataSize, blob->length);
2437         memcpy(outData, blob->data, *outDataSize);
2438     } else {
2439         *outDataSize = blob->length;
2440     }
2441     drmModeFreePropertyBlob(blob);
2442     *outPort = mDrmConnector->id();
2443 
2444     return HWC2_ERROR_NONE;
2445 }
2446