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 #ifndef _EXYNOSDISPLAYDRMINTERFACE_H
18 #define _EXYNOSDISPLAYDRMINTERFACE_H
19
20 #include <drm/samsung_drm.h>
21 #include <utils/Condition.h>
22 #include <utils/Mutex.h>
23 #include <xf86drmMode.h>
24
25 #include <list>
26 #include <unordered_map>
27
28 #include "ExynosDisplay.h"
29 #include "ExynosDisplayInterface.h"
30 #include "ExynosHWC.h"
31 #include "ExynosMPP.h"
32 #include "drmconnector.h"
33 #include "drmcrtc.h"
34 #include "histogram/histogram.h"
35 #include "vsyncworker.h"
36
37 /* Max plane number of buffer object */
38 #define HWC_DRM_BO_MAX_PLANES 4
39
40 /* Monitor Descriptor data is 13 bytes in VESA EDID Standard */
41 #define MONITOR_DESCRIPTOR_DATA_LENGTH 13
42
43 #ifndef HWC_FORCE_PANIC_PATH
44 #define HWC_FORCE_PANIC_PATH "/d/dpu/panic"
45 #endif
46
47 using namespace android;
48
49 class ExynosDevice;
50
51 template <typename T>
52 using DrmArray = std::array<T, HWC_DRM_BO_MAX_PLANES>;
53
54 class DisplayConfigGroupIdGenerator {
55 public:
56 DisplayConfigGroupIdGenerator() = default;
57 ~DisplayConfigGroupIdGenerator() = default;
58
59 // Vrr will utilize the last two parameters. In the case of non-vrr, they are automatically set
60 // to 0. Avoid using this class with a mix of Vrr and non-Vrr settings, as doing so may yield
61 // unexpected results.
62 int getGroupId(int width, int height, int minFrameInterval = 0, int vsyncPeriod = 0) {
63 const auto &key = std::make_tuple(width, height, minFrameInterval, vsyncPeriod);
64 if (groups_.count(key) > 0) {
65 return groups_[key];
66 }
67 size_t last_id = groups_.size();
68 groups_[key] = last_id;
69 return last_id;
70 }
71
72 private:
73 std::map<std::tuple<int, int, int, int>, int> groups_;
74 };
75
76 class FramebufferManager {
77 public:
FramebufferManager()78 FramebufferManager(){};
79 ~FramebufferManager();
80 void init(int drmFd);
81
82 // get buffer for provided config, if a buffer with same config is already cached it will be
83 // reused otherwise one will be allocated. returns fbId that can be used to attach to the
84 // plane, any buffers allocated/reused with this call will be bound to the corresponding
85 // layer. Those fbIds will be cleaned up once the layer was destroyed.
86 int32_t getBuffer(const exynos_win_config_data &config, uint32_t &fbId);
87
88 void checkShrink();
89
90 void cleanup(const ExynosLayer *layer);
91 void destroyAllSecureBuffers();
92 int32_t uncacheLayerBuffers(const ExynosLayer* layer,
93 const std::vector<buffer_handle_t>& buffers);
94
95 // The flip function is to help clean up the cached fbIds of destroyed
96 // layers after the previous fdIds were update successfully on the
97 // screen.
98 // This should be called after the frame update.
99 void flip(const bool hasSecureBuffer);
100
101 // release all currently tracked buffers, this can be called for example when display is turned
102 // off
103 void releaseAll();
104
105 private:
106 // this struct should contain elements that can be used to identify framebuffer more easily
107 struct Framebuffer {
108 struct BufferDesc {
109 uint64_t bufferId;
110 int drmFormat;
111 bool isSecure;
112 bool operator==(const Framebuffer::BufferDesc &rhs) const {
113 return (bufferId == rhs.bufferId && drmFormat == rhs.drmFormat &&
114 isSecure == rhs.isSecure);
115 }
116 bool operator<(const Framebuffer::BufferDesc& rhs) const {
117 if (bufferId != rhs.bufferId) {
118 return bufferId < rhs.bufferId;
119 }
120 if (drmFormat != rhs.drmFormat) {
121 return drmFormat < rhs.drmFormat;
122 }
123 return isSecure < rhs.isSecure;
124 }
125 };
126 struct SolidColorDesc {
127 uint32_t width;
128 uint32_t height;
129 bool operator==(const Framebuffer::SolidColorDesc &rhs) const {
130 return (width == rhs.width && height == rhs.height);
131 }
132 };
133
FramebufferFramebuffer134 explicit Framebuffer(int fd, uint32_t fb, BufferDesc desc)
135 : drmFd(fd), fbId(fb), bufferDesc(desc){};
FramebufferFramebuffer136 explicit Framebuffer(int fd, uint32_t fb, SolidColorDesc desc)
137 : drmFd(fd), fbId(fb), colorDesc(desc){};
~FramebufferFramebuffer138 ~Framebuffer() { drmModeRmFB(drmFd, fbId); };
139 int drmFd;
140 uint32_t fbId;
141 union {
142 BufferDesc bufferDesc;
143 SolidColorDesc colorDesc;
144 };
145 };
146 using FBList = std::list<std::unique_ptr<Framebuffer>>;
147
148 template <class UnaryPredicate>
149 uint32_t findCachedFbId(const ExynosLayer* layer, const bool isSecureBuffer,
150 UnaryPredicate predicate);
151 int addFB2WithModifiers(uint32_t state, uint32_t width, uint32_t height, uint32_t drmFormat,
152 const DrmArray<uint32_t> &handles,
153 const DrmArray<uint32_t> &pitches,
154 const DrmArray<uint32_t> &offsets,
155 const DrmArray<uint64_t> &modifier, uint32_t *buf_id,
156 uint32_t flags);
157 bool validateLayerInfo(uint32_t state, uint32_t pixel_format,
158 const DrmArray<uint32_t> &handles,
159 const DrmArray<uint64_t> &modifier);
160 uint32_t getBufHandleFromFd(int fd);
161 void freeBufHandle(uint32_t handle);
162 void removeFBsThreadRoutine();
163
164 void markInuseLayerLocked(const ExynosLayer* layer, const bool isSecureBuffer)
165 REQUIRES(mMutex);
166 void destroyUnusedLayersLocked() REQUIRES(mMutex);
167 void destroyAllSecureBuffersLocked() REQUIRES(mMutex);
168
169 int mDrmFd = -1;
170
171 // mCachedLayerBuffers map keep the relationship between Layer and FBList.
172 // mCachedSecureLayerBuffers map keep the relationship between secure
173 // Layer and FBList. The map entry will be deleted once the layer is destroyed.
174 std::map<const ExynosLayer *, FBList> mCachedLayerBuffers;
175 std::map<const ExynosLayer*, FBList> mCachedSecureLayerBuffers;
176
177 // mCleanBuffers list keeps fbIds of destroyed layers. Those fbIds will
178 // be destroyed in mRmFBThread thread.
179 FBList mCleanBuffers;
180
181 // mCacheShrinkPending is set when we want to clean up unused layers
182 // in mCachedLayerBuffers. When the flag is set, mCachedLayersInuse will
183 // keep in-use layers in this frame update. Those unused layers will be
184 // freed at the end of the update. mCacheSecureShrinkPending is same to
185 // mCacheShrinkPending but for mCachedSecureLayerBuffers.
186 // TODO: have a better way to maintain inuse layers
187 bool mCacheShrinkPending = false;
188 bool mCacheSecureShrinkPending = false;
189 std::set<const ExynosLayer *> mCachedLayersInuse;
190 std::set<const ExynosLayer*> mCachedSecureLayersInuse;
191
192 std::thread mRmFBThread;
193 bool mRmFBThreadRunning = false;
194 Condition mFlipDone;
195 Mutex mMutex;
196
197 static constexpr size_t MAX_CACHED_LAYERS = 16;
198 static constexpr size_t MAX_CACHED_SECURE_LAYERS = 1;
199 static constexpr size_t MAX_CACHED_BUFFERS_PER_LAYER = 32;
200 static constexpr size_t MAX_CACHED_SECURE_BUFFERS_PER_LAYER = 3;
201 };
202
203 template <class UnaryPredicate>
findCachedFbId(const ExynosLayer * layer,const bool isSecureBuffer,UnaryPredicate predicate)204 uint32_t FramebufferManager::findCachedFbId(const ExynosLayer* layer, const bool isSecureBuffer,
205 UnaryPredicate predicate) {
206 Mutex::Autolock lock(mMutex);
207 markInuseLayerLocked(layer, isSecureBuffer);
208 const auto& cachedBuffers =
209 (!isSecureBuffer) ? mCachedLayerBuffers[layer] : mCachedSecureLayerBuffers[layer];
210 const auto it = std::find_if(cachedBuffers.begin(), cachedBuffers.end(), predicate);
211 return (it != cachedBuffers.end()) ? (*it)->fbId : 0;
212 }
213
214 class ExynosDisplayDrmInterface :
215 public ExynosDisplayInterface,
216 public VsyncCallback
217 {
218 public:
219 class DrmModeAtomicReq {
220 public:
221 DrmModeAtomicReq(ExynosDisplayDrmInterface *displayInterface);
222 ~DrmModeAtomicReq();
223
224 DrmModeAtomicReq(const DrmModeAtomicReq&) = delete;
225 DrmModeAtomicReq& operator=(const DrmModeAtomicReq&) = delete;
226
pset()227 drmModeAtomicReqPtr pset() { return mPset; };
savePset()228 void savePset() {
229 if (mSavedPset) {
230 drmModeAtomicFree(mSavedPset);
231 }
232 mSavedPset = drmModeAtomicDuplicate(mPset);
233 }
restorePset()234 void restorePset() {
235 if (mPset) {
236 drmModeAtomicFree(mPset);
237 }
238 mPset = mSavedPset;
239 mSavedPset = NULL;
240 }
241
setError(int err)242 void setError(int err) { mError = err; };
getError()243 int getError() { return mError; };
244 int32_t atomicAddProperty(const uint32_t id,
245 const DrmProperty &property,
246 uint64_t value, bool optional = false);
247 String8& dumpAtomicCommitInfo(String8 &result, bool debugPrint = false);
248 int commit(uint32_t flags, bool loggingForDebug = false);
addOldBlob(uint32_t blob_id)249 void addOldBlob(uint32_t blob_id) {
250 mOldBlobs.push_back(blob_id);
251 };
destroyOldBlobs()252 int destroyOldBlobs() {
253 for (auto &blob : mOldBlobs) {
254 int ret = mDrmDisplayInterface->mDrmDevice->DestroyPropertyBlob(blob);
255 if (ret) {
256 HWC_LOGE(mDrmDisplayInterface->mExynosDisplay,
257 "Failed to destroy old blob after commit %d", ret);
258 return ret;
259 }
260 }
261 mOldBlobs.clear();
262 return NO_ERROR;
263 };
264 void dumpDrmAtomicCommitMessage(int err);
265
setAckCallback(std::function<void ()> callback)266 void setAckCallback(std::function<void()> callback) {
267 mAckCallback = std::move(callback);
268 };
269
270 private:
271 drmModeAtomicReqPtr mPset;
272 drmModeAtomicReqPtr mSavedPset;
273 int mError = 0;
274 ExynosDisplayDrmInterface *mDrmDisplayInterface = NULL;
275 /* Destroy old blobs after commit */
276 std::vector<uint32_t> mOldBlobs;
drmFd()277 int drmFd() const { return mDrmDisplayInterface->mDrmDevice->fd(); }
278
279 std::function<void()> mAckCallback;
280
281 static constexpr uint32_t kAllowDumpDrmAtomicMessageTimeMs = 5000U;
282 static constexpr const char* kDrmModuleParametersDebugNode =
283 "/sys/module/drm/parameters/debug";
284 static constexpr const int kEnableDrmAtomicMessage = 16;
285 static constexpr const int kDisableDrmDebugMessage = 0;
286
287 };
288 class ExynosVsyncCallback {
289 public:
enableVSync(bool enable)290 void enableVSync(bool enable) {
291 mVsyncEnabled = enable;
292 resetVsyncTimeStamp();
293 };
getVSyncEnabled()294 bool getVSyncEnabled() { return mVsyncEnabled; };
setDesiredVsyncPeriod(uint64_t period)295 void setDesiredVsyncPeriod(uint64_t period) {
296 mDesiredVsyncPeriod = period;
297 resetVsyncTimeStamp();
298 };
getDesiredVsyncPeriod()299 uint64_t getDesiredVsyncPeriod() { return mDesiredVsyncPeriod;};
getVsyncTimeStamp()300 uint64_t getVsyncTimeStamp() { return mVsyncTimeStamp; };
getVsyncPeriod()301 uint64_t getVsyncPeriod() { return mVsyncPeriod; };
302 bool Callback(int display, int64_t timestamp);
resetVsyncTimeStamp()303 void resetVsyncTimeStamp() { mVsyncTimeStamp = 0; };
resetDesiredVsyncPeriod()304 void resetDesiredVsyncPeriod() { mDesiredVsyncPeriod = 0;};
305 private:
306 bool mVsyncEnabled = false;
307 uint64_t mVsyncTimeStamp = 0;
308 uint64_t mVsyncPeriod = 0;
309 uint64_t mDesiredVsyncPeriod = 0;
310 };
311 void Callback(int display, int64_t timestamp) override;
312
313 ExynosDisplayDrmInterface(ExynosDisplay *exynosDisplay);
314 ~ExynosDisplayDrmInterface();
315 virtual void init(ExynosDisplay *exynosDisplay);
316 virtual int32_t setPowerMode(int32_t mode);
317 virtual int32_t setLowPowerMode() override;
isDozeModeAvailable()318 virtual bool isDozeModeAvailable() const {
319 return mDozeDrmMode.h_display() > 0 && mDozeDrmMode.v_display() > 0;
320 };
321 virtual int32_t setVsyncEnabled(uint32_t enabled);
322 virtual int32_t getDisplayConfigs(
323 uint32_t* outNumConfigs,
324 hwc2_config_t* outConfigs);
325 virtual void dumpDisplayConfigs();
326 virtual bool supportDataspace(int32_t dataspace);
327 virtual int32_t getColorModes(uint32_t* outNumModes, int32_t* outModes);
328 virtual int32_t setColorMode(int32_t mode);
329 virtual int32_t setActiveConfig(hwc2_config_t config);
330 virtual int32_t setCursorPositionAsync(uint32_t x_pos, uint32_t y_pos);
331 virtual int32_t updateHdrCapabilities();
332 virtual int32_t deliverWinConfigData();
333 virtual int32_t clearDisplay(bool needModeClear = false);
334 virtual int32_t disableSelfRefresh(uint32_t disable);
335 virtual int32_t setForcePanic();
getDisplayFd()336 virtual int getDisplayFd() { return mDrmDevice->fd(); };
337 virtual int32_t initDrmDevice(DrmDevice *drmDevice);
338 virtual int getDrmDisplayId(uint32_t type, uint32_t index);
getMaxWindowNum()339 virtual uint32_t getMaxWindowNum() { return mMaxWindowNum; };
340 virtual int32_t getReadbackBufferAttributes(int32_t* /*android_pixel_format_t*/ outFormat,
341 int32_t* /*android_dataspace_t*/ outDataspace);
342 virtual int32_t getDisplayIdentificationData(uint8_t* outPort,
343 uint32_t* outDataSize, uint8_t* outData);
344 virtual bool needRefreshOnLP();
345
346 /* For HWC 2.4 APIs */
347 virtual int32_t getDisplayVsyncPeriod(
348 hwc2_vsync_period_t* outVsyncPeriod);
349 virtual int32_t getConfigChangeDuration();
350 virtual int32_t getVsyncAppliedTime(hwc2_config_t config,
351 int64_t* actualChangeTime);
352 virtual int32_t setActiveConfigWithConstraints(
353 hwc2_config_t config, bool test = false);
354
setDisplayColorSetting(ExynosDisplayDrmInterface::DrmModeAtomicReq __unused & drmReq)355 virtual int32_t setDisplayColorSetting(
356 ExynosDisplayDrmInterface::DrmModeAtomicReq __unused &drmReq) {
357 return NO_ERROR;
358 }
setPlaneColorSetting(ExynosDisplayDrmInterface::DrmModeAtomicReq & drmReq,const std::unique_ptr<DrmPlane> & plane,const exynos_win_config_data & config,uint32_t & solidColor)359 virtual int32_t setPlaneColorSetting(
360 ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq,
361 const std::unique_ptr<DrmPlane> &plane,
362 const exynos_win_config_data& config,
363 uint32_t &solidColor)
364 { return NO_ERROR;};
365 virtual void destroyLayer(ExynosLayer *layer) override;
366
367 /* For HWC 3.0 APIs */
368 virtual int32_t getDisplayIdleTimerSupport(bool &outSupport);
369 virtual int32_t getDefaultModeId(int32_t *modeId) override;
370
371 virtual int32_t waitVBlank();
getDesiredRefreshRate()372 float getDesiredRefreshRate() { return mDesiredModeState.mode.v_refresh(); }
getOperationRate()373 int32_t getOperationRate() {
374 if (mExynosDisplay->mOperationRateManager) {
375 return mExynosDisplay->mOperationRateManager->getTargetOperationRate();
376 }
377 return 0;
378 }
379
380 /* For Histogram */
setDisplayHistogramSetting(ExynosDisplayDrmInterface::DrmModeAtomicReq & drmReq)381 virtual int32_t setDisplayHistogramSetting(
382 ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq) {
383 return NO_ERROR;
384 }
385
386 /* For Histogram Multi Channel support */
387 int32_t setHistogramChannelConfigBlob(ExynosDisplayDrmInterface::DrmModeAtomicReq& drmReq,
388 uint8_t channelId, uint32_t blobId);
389 int32_t clearHistogramChannelConfigBlob(ExynosDisplayDrmInterface::DrmModeAtomicReq& drmReq,
390 uint8_t channelId);
391 enum class HistogramChannelIoctl_t {
392 /* send the histogram data request by calling histogram_channel_request_ioctl */
393 REQUEST = 0,
394
395 /* cancel the histogram data request by calling histogram_channel_cancel_ioctl */
396 CANCEL,
397 };
398 int32_t sendHistogramChannelIoctl(HistogramChannelIoctl_t control, uint32_t blobId) const;
399
400 enum class ContextHistogramIoctl_t {
401 /* send the histogram event request by calling histogram_event_request_ioctl */
402 REQUEST = 0,
403 /* send the histogram event request by calling histogram_event_cancel_ioctl */
404 CANCEL,
405 };
406 int32_t sendContextHistogramIoctl(ContextHistogramIoctl_t control, uint32_t blobId) const;
407
getFrameCount()408 int32_t getFrameCount() { return mFrameCounter; }
registerHistogramInfo(const std::shared_ptr<IDLHistogram> & info)409 virtual void registerHistogramInfo(const std::shared_ptr<IDLHistogram> &info) { return; }
setHistogramControl(hidl_histogram_control_t enabled)410 virtual int32_t setHistogramControl(hidl_histogram_control_t enabled) { return NO_ERROR; }
setHistogramData(void * bin)411 virtual int32_t setHistogramData(void *bin) { return NO_ERROR; }
getActiveModeHDisplay()412 int32_t getActiveModeHDisplay() { return mActiveModeState.mode.h_display(); }
getActiveModeVDisplay()413 int32_t getActiveModeVDisplay() { return mActiveModeState.mode.v_display(); }
getActiveModeId()414 uint32_t getActiveModeId() { return mActiveModeState.mode.id(); }
getPanelFullResolutionHSize()415 int32_t getPanelFullResolutionHSize() { return mPanelFullResolutionHSize; }
getPanelFullResolutionVSize()416 int32_t getPanelFullResolutionVSize() { return mPanelFullResolutionVSize; }
getCrtcId()417 uint32_t getCrtcId() { return mDrmCrtc->id(); }
418 int32_t triggerClearDisplayPlanes();
419
420 virtual void setXrrSettings(const XrrSettings_t& settings) override;
isVrrSupported()421 bool isVrrSupported() const { return mXrrSettings.versionInfo.isVrr(); }
isMrrV2()422 bool isMrrV2() const {
423 return (!mXrrSettings.versionInfo.isVrr()) &&
424 (mXrrSettings.versionInfo.minorVersion == 2);
425 }
426
427 void handleDrmPropertyUpdate(uint32_t connector_id, uint32_t prop_id);
428
429 /* store the manufacturer info and product id from EDID
430 * - Manufacturer ID is stored in EDID byte 8 and 9.
431 * - Manufacturer product ID is stored in EDID byte 10 and 11.
432 */
433 virtual void setManufacturerInfo(uint8_t edid8, uint8_t edid9) override;
getManufacturerInfo()434 virtual uint32_t getManufacturerInfo() override { return mManufacturerInfo; }
435 virtual void setProductId(uint8_t edid10, uint8_t edid11) override;
getProductId()436 virtual uint32_t getProductId() override { return mProductId; }
437
438 // This function will swap crtc/decon assigned to this display, with the crtc/decon of
439 // the provided |anotherDisplay|. It is used on foldable devices, where decon0/1 support
440 // color management, but decon2 doesn't, to re-assign the decon0/1 of a powered off primary
441 // display for the external display. When the external display is disconnected, this
442 // function is called again with the same |anotherDisplay| parameter to restore the
443 // original crtc/decon assignment of the external and primary display.
444 // See b/329034082 for details.
445 virtual int32_t swapCrtcs(ExynosDisplay* anotherDisplay) override;
446 // After swapCrtcs has been successfully done, this function will return the display, whose
447 // crtc/decon this display is currently using.
448 virtual ExynosDisplay* borrowedCrtcFrom() override;
449
450 virtual int32_t uncacheLayerBuffers(const ExynosLayer* __unused layer,
451 const std::vector<buffer_handle_t>& buffers) override;
452
453 protected:
454 enum class HalMipiSyncType : uint32_t {
455 HAL_MIPI_CMD_SYNC_REFRESH_RATE = 0,
456 HAL_MIPI_CMD_SYNC_LHBM,
457 HAL_MIPI_CMD_SYNC_GHBM,
458 HAL_MIPI_CMD_SYNC_BL,
459 HAL_MIPI_CMD_SYNC_OP_RATE,
460 };
461
462 struct ModeState {
463 enum ModeStateType {
464 MODE_STATE_NONE = 0U,
465 MODE_STATE_REFRESH_RATE = 1U << 0,
466 MODE_STATE_RESOLUTION = 1U << 1,
467 MODE_STATE_FORCE_MODE_SET = 1U << 2,
468 };
469 DrmMode mode;
470 uint32_t blob_id = 0;
471 uint32_t old_blob_id = 0;
setModeModeState472 void setMode(const DrmMode newMode, const uint32_t modeBlob,
473 DrmModeAtomicReq &drmReq) {
474 if (newMode.v_refresh() != mode.v_refresh()) {
475 mModeState |= ModeStateType::MODE_STATE_REFRESH_RATE;
476 }
477 if (isFullModeSwitch(newMode)) {
478 mModeState |= ModeStateType::MODE_STATE_RESOLUTION;
479 }
480
481 drmReq.addOldBlob(old_blob_id);
482 mode = newMode;
483 old_blob_id = blob_id;
484 blob_id = modeBlob;
485 };
resetModeState486 void reset() {
487 *this = {};
488 };
applyModeState489 void apply(ModeState &toModeState, DrmModeAtomicReq &drmReq) {
490 toModeState.setMode(mode, blob_id, drmReq);
491 drmReq.addOldBlob(old_blob_id);
492 reset();
493 };
494
495 int32_t mModeState = ModeStateType::MODE_STATE_NONE;
forceModeSetModeState496 void forceModeSet() { mModeState |= ModeStateType::MODE_STATE_FORCE_MODE_SET; }
clearPendingModeStateModeState497 void clearPendingModeState() { mModeState = ModeStateType::MODE_STATE_NONE; }
needsModeSetModeState498 bool needsModeSet() const { return mModeState != ModeStateType::MODE_STATE_NONE; }
isSeamlessModeState499 bool isSeamless() const { return !(mModeState & ModeStateType::MODE_STATE_RESOLUTION); }
isFullModeSwitchModeState500 bool isFullModeSwitch(const DrmMode &newMode) {
501 if ((mode.h_display() != newMode.h_display()) ||
502 (mode.v_display() != newMode.v_display()))
503 return true;
504 return false;
505 }
506 };
507 int32_t createModeBlob(const DrmMode &mode, uint32_t &modeBlob);
508 int32_t setDisplayMode(DrmModeAtomicReq& drmReq, const uint32_t& modeBlob,
509 const uint32_t& modeId);
510 int32_t clearDisplayMode(DrmModeAtomicReq &drmReq);
511 int32_t clearDisplayPlanes(DrmModeAtomicReq &drmReq);
512 int32_t choosePreferredConfig();
513 int getDeconChannel(ExynosMPP *otfMPP);
514 /*
515 * This function adds FB and gets new fb id if fbId is 0,
516 * if fbId is not 0, this reuses fbId.
517 */
518 int32_t setupCommitFromDisplayConfig(DrmModeAtomicReq &drmReq,
519 const exynos_win_config_data &config,
520 const uint32_t configIndex,
521 const std::unique_ptr<DrmPlane> &plane,
522 uint32_t &fbId);
523
524 int32_t setupPartialRegion(DrmModeAtomicReq &drmReq);
525 void parseBlendEnums(const DrmProperty &property);
526 void parseStandardEnums(const DrmProperty &property);
527 void parseTransferEnums(const DrmProperty &property);
528 void parseRangeEnums(const DrmProperty &property);
529 void parseColorModeEnums(const DrmProperty &property);
530 void parseMipiSyncEnums(const DrmProperty &property);
531 void updateMountOrientation();
532 void parseRCDId(const DrmProperty &property);
533
534 int32_t setupWritebackCommit(DrmModeAtomicReq &drmReq);
535 int32_t clearWritebackCommit(DrmModeAtomicReq &drmReq);
536
537 private:
538 int32_t updateColorSettings(DrmModeAtomicReq &drmReq, uint64_t dqeEnabled);
539 int32_t getLowPowerDrmModeModeInfo();
540 int32_t setActiveDrmMode(DrmMode const &mode);
setMaxWindowNum(uint32_t num)541 void setMaxWindowNum(uint32_t num) { mMaxWindowNum = num; };
542 int32_t getSpecialChannelId(uint32_t planeId);
543
544 protected:
545 struct PartialRegionState {
546 struct drm_clip_rect partial_rect = {0, 0, 0, 0};
547 uint32_t blob_id = 0;
isUpdatedPartialRegionState548 bool isUpdated(drm_clip_rect rect) {
549 return ((partial_rect.x1 != rect.x1) ||
550 (partial_rect.y1 != rect.y1) ||
551 (partial_rect.x2 != rect.x2) ||
552 (partial_rect.y2 != rect.y2));
553 };
554 };
555
556 struct BlockingRegionState {
557 struct decon_win_rect mRegion;
558 uint32_t mBlobId = 0;
559
560 inline bool operator==(const decon_win_rect &rhs) const {
561 return mRegion.x == rhs.x && mRegion.y == rhs.y && mRegion.w == rhs.w &&
562 mRegion.h == rhs.h;
563 }
564 inline bool operator!=(const decon_win_rect &rhs) const { return !(*this == rhs); }
565 };
566
567 class DrmReadbackInfo {
568 public:
569 void init(DrmDevice *drmDevice, uint32_t displayId);
~DrmReadbackInfo()570 ~DrmReadbackInfo() {
571 if (mDrmDevice == NULL)
572 return;
573 if (mOldFbId > 0)
574 drmModeRmFB(mDrmDevice->fd(), mOldFbId);
575 if (mFbId > 0)
576 drmModeRmFB(mDrmDevice->fd(), mFbId);
577 }
getWritebackConnector()578 DrmConnector* getWritebackConnector() { return mWritebackConnector; };
setFbId(uint32_t fbId)579 void setFbId(uint32_t fbId) {
580 if ((mDrmDevice != NULL) && (mOldFbId > 0))
581 drmModeRmFB(mDrmDevice->fd(), mOldFbId);
582 mOldFbId = mFbId;
583 mFbId = fbId;
584 }
585 void pickFormatDataspace();
586 static constexpr uint32_t PREFERRED_READBACK_FORMAT =
587 HAL_PIXEL_FORMAT_RGBA_8888;
588 uint32_t mReadbackFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
589 bool mNeedClearReadbackCommit = false;
590 private:
591 DrmDevice *mDrmDevice = NULL;
592 DrmConnector *mWritebackConnector = NULL;
593 uint32_t mFbId = 0;
594 uint32_t mOldFbId = 0;
595 std::vector<uint32_t> mSupportedFormats;
596 };
597 DrmDevice *mDrmDevice;
598 DrmCrtc *mDrmCrtc;
599 DrmConnector *mDrmConnector;
600 VSyncWorker mDrmVSyncWorker;
601 ExynosVsyncCallback mVsyncCallback;
602 ModeState mActiveModeState;
603 ModeState mDesiredModeState;
604 PartialRegionState mPartialRegionState;
605 BlockingRegionState mBlockState;
606 /* Mapping plane id to ExynosMPP, key is plane id */
607 std::unordered_map<uint32_t, ExynosMPP*> mExynosMPPsForPlane;
608
609 ExynosDisplay* mBorrowedCrtcFrom = nullptr;
610
611 DrmEnumParser::MapHal2DrmEnum mBlendEnums;
612 DrmEnumParser::MapHal2DrmEnum mStandardEnums;
613 DrmEnumParser::MapHal2DrmEnum mTransferEnums;
614 DrmEnumParser::MapHal2DrmEnum mRangeEnums;
615 DrmEnumParser::MapHal2DrmEnum mColorModeEnums;
616 DrmEnumParser::MapHal2DrmEnum mMipiSyncEnums;
617
618 DrmReadbackInfo mReadbackInfo;
619 FramebufferManager mFBManager;
620 std::array<uint8_t, MONITOR_DESCRIPTOR_DATA_LENGTH> mMonitorDescription;
621 nsecs_t mLastDumpDrmAtomicMessageTime;
622 bool mIsResolutionSwitchInProgress = false;
623
624 private:
625 int32_t getDisplayFakeEdid(uint8_t &outPort, uint32_t &outDataSize, uint8_t *outData);
626
627 String8 mDisplayTraceName;
628 DrmMode mDozeDrmMode;
629 uint32_t mMaxWindowNum = 0;
630 int32_t mFrameCounter = 0;
631 int32_t mPanelFullResolutionHSize = 0;
632 int32_t mPanelFullResolutionVSize = 0;
633
634 // Vrr related settings.
635 XrrSettings_t mXrrSettings;
636
637 /**
638 * retrievePanelFullResolution
639 *
640 * Retrieve the panel full resolution by looking into the modes of the mDrmConnector
641 * and store the full resolution info in mPanelFullResolutionHSize (x component) and
642 * mPanelFullResolutionVSize (y component).
643 *
644 * Note: this function will be called only once in initDrmDevice()
645 */
646 void retrievePanelFullResolution();
647
648 const uint8_t kEDIDManufacturerIDByte1 = 8;
649 const uint8_t kEDIDManufacturerIDByte2 = 9;
650 const uint8_t kEDIDProductIDByte1 = 10;
651 const uint8_t kEDIDProductIDByte2 = 11;
652 uint32_t mManufacturerInfo;
653 uint32_t mProductId;
654 bool mIsFirstClean = true;
655
656 public:
657 virtual bool readHotplugStatus();
658 virtual int readHotplugErrorCode();
659 virtual void resetHotplugErrorCode();
660 };
661
662 #endif
663