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