• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "BrightnessController.h"
18 #include "ExynosDisplayDrmInterfaceModule.h"
19 #include "ExynosPrimaryDisplayModule.h"
20 #include <drm/samsung_drm.h>
21 
22 using BrightnessRange = BrightnessController::BrightnessRange;
23 
24 using namespace gs101;
25 
26 /////////////////////////////////////////////////// ExynosDisplayDrmInterfaceModule //////////////////////////////////////////////////////////////////
ExynosDisplayDrmInterfaceModule(ExynosDisplay * exynosDisplay)27 ExynosDisplayDrmInterfaceModule::ExynosDisplayDrmInterfaceModule(ExynosDisplay *exynosDisplay)
28 : ExynosDisplayDrmInterface(exynosDisplay)
29 {
30 }
31 
~ExynosDisplayDrmInterfaceModule()32 ExynosDisplayDrmInterfaceModule::~ExynosDisplayDrmInterfaceModule()
33 {
34 }
35 
parseBpcEnums(const DrmProperty & property)36 void ExynosDisplayDrmInterfaceModule::parseBpcEnums(const DrmProperty& property)
37 {
38     const std::vector<std::pair<uint32_t, const char *>> bpcEnums = {
39         {static_cast<uint32_t>(BPC_UNSPECIFIED), "Unspecified"},
40         {static_cast<uint32_t>(BPC_8), "8bpc"},
41         {static_cast<uint32_t>(BPC_10), "10bpc"},
42     };
43 
44     ALOGD("Init bpc enums");
45     DrmEnumParser::parseEnums(property, bpcEnums, mBpcEnums);
46     for (auto &e : mBpcEnums) {
47         ALOGD("bpc [bpc: %d, drm: %" PRId64 "]", e.first, e.second);
48     }
49 }
50 
initDrmDevice(DrmDevice * drmDevice)51 int32_t ExynosDisplayDrmInterfaceModule::initDrmDevice(DrmDevice *drmDevice)
52 {
53     int ret = NO_ERROR;
54     if ((ret = ExynosDisplayDrmInterface::initDrmDevice(drmDevice)) != NO_ERROR)
55         return ret;
56 
57     if (isPrimary() == false)
58         return ret;
59 
60     mOldDqeBlobs.init(drmDevice);
61 
62     initOldDppBlobs(drmDevice);
63     if (mDrmCrtc->force_bpc_property().id())
64         parseBpcEnums(mDrmCrtc->force_bpc_property());
65 
66     mOldHistoBlobs.init(drmDevice);
67 
68     return ret;
69 }
70 
destroyOldBlobs(std::vector<uint32_t> & oldBlobs)71 void ExynosDisplayDrmInterfaceModule::destroyOldBlobs(
72         std::vector<uint32_t> &oldBlobs)
73 {
74     for (auto &blob : oldBlobs) {
75         mDrmDevice->DestroyPropertyBlob(blob);
76     }
77     oldBlobs.clear();
78 }
79 
80 template<typename StageDataType>
setDisplayColorBlob(const DrmProperty & prop,const uint32_t type,const StageDataType & stage,const typename GsInterfaceType::IDqe & dqe,ExynosDisplayDrmInterface::DrmModeAtomicReq & drmReq)81 int32_t ExynosDisplayDrmInterfaceModule::setDisplayColorBlob(
82         const DrmProperty &prop,
83         const uint32_t type,
84         const StageDataType &stage,
85         const typename GsInterfaceType::IDqe &dqe,
86         ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq)
87 {
88     /* dirty bit is valid only if enable is true */
89     if (!prop.id())
90         return NO_ERROR;
91     if (!mForceDisplayColorSetting && stage.enable && !stage.dirty)
92         return NO_ERROR;
93 
94     int32_t ret = 0;
95     uint32_t blobId = 0;
96     uint64_t lutSize;
97 
98     if (stage.enable) {
99         switch (type) {
100             case DqeBlobs::CGC:
101                 ret = gs::ColorDrmBlobFactory::cgc(dqe.Cgc().config, mDrmDevice, blobId);
102                 break;
103             case DqeBlobs::DEGAMMA_LUT:
104                 std::tie(ret, lutSize) = mDrmCrtc->degamma_lut_size_property().value();
105                 if (ret < 0) {
106                     HWC_LOGE(mExynosDisplay, "%s: there is no degamma_lut_size (ret = %d)",
107                              __func__, ret);
108                 } else {
109                     ret = gs::ColorDrmBlobFactory::degamma(lutSize, dqe.DegammaLut().config,
110                                                            mDrmDevice, blobId);
111                 }
112                 break;
113             case DqeBlobs::REGAMMA_LUT:
114                 std::tie(ret, lutSize) = mDrmCrtc->gamma_lut_size_property().value();
115                 if (ret < 0) {
116                     HWC_LOGE(mExynosDisplay, "%s: there is no gamma_lut_size (ret = %d)", __func__,
117                              ret);
118                 } else {
119                     ret = gs::ColorDrmBlobFactory::regamma(lutSize, dqe.RegammaLut().config,
120                                                            mDrmDevice, blobId);
121                 }
122                 break;
123             case DqeBlobs::GAMMA_MAT:
124                 ret = gs::ColorDrmBlobFactory::gammaMatrix(dqe.GammaMatrix().config, mDrmDevice,
125                                                         blobId);
126                 break;
127             case DqeBlobs::LINEAR_MAT:
128                 ret = gs::ColorDrmBlobFactory::linearMatrix(dqe.LinearMatrix().config, mDrmDevice,
129                                                          blobId);
130                 break;
131             case DqeBlobs::DISP_DITHER:
132                 ret = gs::ColorDrmBlobFactory::displayDither(dqe.DqeControl().config, mDrmDevice,
133                                                           blobId);
134                 break;
135             case DqeBlobs::CGC_DITHER:
136                 ret = gs::ColorDrmBlobFactory::cgcDither(dqe.DqeControl().config, mDrmDevice, blobId);
137                 break;
138             default:
139                 ret = -EINVAL;
140         }
141         if (ret != NO_ERROR) {
142             HWC_LOGE(mExynosDisplay, "%s: create blob fail", __func__);
143             return ret;
144         }
145     }
146 
147     /* Skip setting when previous and current setting is same with 0 */
148     if ((blobId == 0) && (mOldDqeBlobs.getBlob(type) == 0))
149         return ret;
150 
151     if ((ret = drmReq.atomicAddProperty(mDrmCrtc->id(), prop, blobId)) < 0) {
152         HWC_LOGE(mExynosDisplay, "%s: Fail to set property",
153                 __func__);
154         return ret;
155     }
156     mOldDqeBlobs.addBlob(type, blobId);
157 
158     // disp_dither and cgc dither are part of DqeCtrl stage and the notification
159     // will be sent after all data in DqeCtrl stage are applied.
160     if (type != DqeBlobs::DISP_DITHER && type != DqeBlobs::CGC_DITHER)
161         stage.NotifyDataApplied();
162 
163     return ret;
164 }
setDisplayColorSetting(ExynosDisplayDrmInterface::DrmModeAtomicReq & drmReq)165 int32_t ExynosDisplayDrmInterfaceModule::setDisplayColorSetting(
166         ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq)
167 {
168     if (isPrimary() == false)
169         return NO_ERROR;
170     if (!mForceDisplayColorSetting && !mColorSettingChanged)
171         return NO_ERROR;
172 
173     ExynosPrimaryDisplayModule* display =
174         (ExynosPrimaryDisplayModule*)mExynosDisplay;
175 
176     int ret = NO_ERROR;
177     const typename GsInterfaceType::IDqe &dqe = display->getDqe();
178 
179     if ((mDrmCrtc->cgc_lut_property().id() != 0) &&
180         (ret = setDisplayColorBlob(mDrmCrtc->cgc_lut_property(),
181                 static_cast<uint32_t>(DqeBlobs::CGC),
182                 dqe.Cgc(), dqe, drmReq) != NO_ERROR)) {
183         HWC_LOGE(mExynosDisplay, "%s: set Cgc blob fail", __func__);
184         return ret;
185     }
186     if ((ret = setDisplayColorBlob(mDrmCrtc->degamma_lut_property(),
187                 static_cast<uint32_t>(DqeBlobs::DEGAMMA_LUT),
188                 dqe.DegammaLut(), dqe, drmReq) != NO_ERROR)) {
189         HWC_LOGE(mExynosDisplay, "%s: set DegammaLut blob fail", __func__);
190         return ret;
191     }
192     if ((ret = setDisplayColorBlob(mDrmCrtc->gamma_lut_property(),
193                 static_cast<uint32_t>(DqeBlobs::REGAMMA_LUT),
194                 dqe.RegammaLut(), dqe, drmReq) != NO_ERROR)) {
195         HWC_LOGE(mExynosDisplay, "%s: set RegammaLut blob fail", __func__);
196         return ret;
197     }
198     if ((ret = setDisplayColorBlob(mDrmCrtc->gamma_matrix_property(),
199                 static_cast<uint32_t>(DqeBlobs::GAMMA_MAT),
200                 dqe.GammaMatrix(), dqe, drmReq) != NO_ERROR)) {
201         HWC_LOGE(mExynosDisplay, "%s: set GammaMatrix blob fail", __func__);
202         return ret;
203     }
204     if ((ret = setDisplayColorBlob(mDrmCrtc->linear_matrix_property(),
205                 static_cast<uint32_t>(DqeBlobs::LINEAR_MAT),
206                 dqe.LinearMatrix(), dqe, drmReq) != NO_ERROR)) {
207         HWC_LOGE(mExynosDisplay, "%s: set LinearMatrix blob fail", __func__);
208         return ret;
209     }
210     if ((ret = setDisplayColorBlob(mDrmCrtc->disp_dither_property(),
211                 static_cast<uint32_t>(DqeBlobs::DISP_DITHER),
212                 dqe.DqeControl(), dqe, drmReq) != NO_ERROR)) {
213         HWC_LOGE(mExynosDisplay, "%s: set DispDither blob fail", __func__);
214         return ret;
215     }
216     if ((ret = setDisplayColorBlob(mDrmCrtc->cgc_dither_property(),
217                 static_cast<uint32_t>(DqeBlobs::CGC_DITHER),
218                 dqe.DqeControl(), dqe, drmReq) != NO_ERROR)) {
219         HWC_LOGE(mExynosDisplay, "%s: set CgcDither blob fail", __func__);
220         return ret;
221     }
222 
223     const DrmProperty &prop_force_bpc = mDrmCrtc->force_bpc_property();
224     if (prop_force_bpc.id()) {
225         uint32_t bpc = static_cast<uint32_t>(BPC_UNSPECIFIED);
226         if (dqe.DqeControl().enable) {
227             if (dqe.DqeControl().config->force_10bpc)
228                 bpc = static_cast<uint32_t>(BPC_10);
229         }
230         auto [bpcEnum, ret] = DrmEnumParser::halToDrmEnum(bpc, mBpcEnums);
231         if (ret < 0) {
232             HWC_LOGE(mExynosDisplay, "Fail to convert bpc(%d)", bpc);
233         } else {
234             if ((ret = drmReq.atomicAddProperty(mDrmCrtc->id(), prop_force_bpc,
235                             bpcEnum, true)) < 0) {
236                 HWC_LOGE(mExynosDisplay, "%s: Fail to set force bpc property",
237                         __func__);
238             }
239         }
240     }
241     dqe.DqeControl().NotifyDataApplied();
242 
243     return NO_ERROR;
244 }
245 
246 template<typename StageDataType>
setPlaneColorBlob(const std::unique_ptr<DrmPlane> & plane,const DrmProperty & prop,const uint32_t type,const StageDataType & stage,const typename GsInterfaceType::IDpp & dpp,const uint32_t dppIndex,ExynosDisplayDrmInterface::DrmModeAtomicReq & drmReq,bool forceUpdate)247 int32_t ExynosDisplayDrmInterfaceModule::setPlaneColorBlob(
248         const std::unique_ptr<DrmPlane> &plane,
249         const DrmProperty &prop,
250         const uint32_t type,
251         const StageDataType &stage,
252         const typename GsInterfaceType::IDpp &dpp,
253         const uint32_t dppIndex,
254         ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq,
255         bool forceUpdate)
256 {
257     /* dirty bit is valid only if enable is true */
258     if (!prop.id() || (stage.enable && !stage.dirty && !forceUpdate))
259         return NO_ERROR;
260 
261     uint32_t ix = 0;
262     for (;ix < mOldDppBlobs.size(); ix++) {
263         if (mOldDppBlobs[ix].planeId == plane->id()) {
264             break;
265         }
266     }
267     if (ix >= mOldDppBlobs.size()) {
268         HWC_LOGE(mExynosDisplay, "%s: could not find plane %d", __func__, plane->id());
269         return -EINVAL;
270     }
271     DppBlobs &oldDppBlobs = mOldDppBlobs[ix];
272 
273     int32_t ret = 0;
274     uint32_t blobId = 0;
275 
276     if (stage.enable) {
277         switch (type) {
278             case DppBlobs::EOTF:
279                 ret = gs::ColorDrmBlobFactory::eotf(dpp.EotfLut().config, mDrmDevice, blobId);
280                 break;
281             case DppBlobs::GM:
282                 ret = gs::ColorDrmBlobFactory::gm(dpp.Gm().config, mDrmDevice, blobId);
283                 break;
284             case DppBlobs::DTM:
285                 ret = gs::ColorDrmBlobFactory::dtm(dpp.Dtm().config, mDrmDevice, blobId);
286                 break;
287             case DppBlobs::OETF:
288                 ret = gs::ColorDrmBlobFactory::oetf(dpp.OetfLut().config, mDrmDevice, blobId);
289                 break;
290             default:
291                 ret = -EINVAL;
292         }
293         if (ret != NO_ERROR) {
294             HWC_LOGE(mExynosDisplay, "%s: create blob fail", __func__);
295             return ret;
296         }
297     }
298 
299     /* Skip setting when previous and current setting is same with 0 */
300     if ((blobId == 0) && (oldDppBlobs.getBlob(type) == 0) && !forceUpdate)
301         return ret;
302 
303     if ((ret = drmReq.atomicAddProperty(plane->id(), prop, blobId)) < 0) {
304         HWC_LOGE(mExynosDisplay, "%s: Fail to set property",
305                 __func__);
306         return ret;
307     }
308 
309     oldDppBlobs.addBlob(type, blobId);
310     stage.NotifyDataApplied();
311 
312     return ret;
313 }
314 
setPlaneColorSetting(ExynosDisplayDrmInterface::DrmModeAtomicReq & drmReq,const std::unique_ptr<DrmPlane> & plane,const exynos_win_config_data & config,uint32_t & solidColor)315 int32_t ExynosDisplayDrmInterfaceModule::setPlaneColorSetting(
316         ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq,
317         const std::unique_ptr<DrmPlane> &plane,
318         const exynos_win_config_data &config, uint32_t &solidColor)
319 {
320     if ((mColorSettingChanged == false) ||
321         (isPrimary() == false))
322         return NO_ERROR;
323 
324     if ((config.assignedMPP == nullptr) ||
325         (config.assignedMPP->mAssignedSources.size() == 0)) {
326         HWC_LOGE(mExynosDisplay, "%s:: config's mpp source size is invalid",
327                 __func__);
328         return -EINVAL;
329     }
330     ExynosMPPSource* mppSource = config.assignedMPP->mAssignedSources[0];
331     if (mppSource->mSourceType >= MPP_SOURCE_MAX) {
332         HWC_LOGE(mExynosDisplay,
333                 "%s: invalid mpp source type (%d)", __func__, mppSource->mSourceType);
334         return -EINVAL;
335     }
336 
337     ExynosPrimaryDisplayModule* display = (ExynosPrimaryDisplayModule*)mExynosDisplay;
338 
339     /*
340      * Color conversion of Client and Exynos composition buffer
341      * is already addressed by GLES or G2D. But as of now, 'dim SDR' is only
342      * supported by HWC/displaycolor, we need put client composition under
343      * control of HWC/displaycolor.
344      */
345     if (!display->hasDppForLayer(mppSource)) {
346         if (mppSource->mSourceType == MPP_SOURCE_LAYER) {
347             HWC_LOGE(mExynosDisplay,
348                 "%s: layer need color conversion but there is no IDpp",
349                 __func__);
350             return -EINVAL;
351         } else if (mppSource->mSourceType == MPP_SOURCE_COMPOSITION_TARGET) {
352             return NO_ERROR;
353         } else {
354             HWC_LOGE(mExynosDisplay,
355                 "%s: invalid mpp source type (%d)", __func__, mppSource->mSourceType);
356             return -EINVAL;
357         }
358     }
359 
360     if (mppSource->mSourceType == MPP_SOURCE_LAYER) {
361         ExynosLayer* layer = (ExynosLayer*)mppSource;
362 
363         /* color conversion was already handled by m2mMPP */
364         if ((layer->mM2mMPP != nullptr) &&
365             (layer->mSrcImg.dataSpace != layer->mMidImg.dataSpace)) {
366             return NO_ERROR;
367         }
368     }
369 
370     const typename GsInterfaceType::IDpp &dpp = display->getDppForLayer(mppSource);
371     const uint32_t dppIndex = static_cast<uint32_t>(display->getDppIndexForLayer(mppSource));
372     bool planeChanged = display->checkAndSaveLayerPlaneId(mppSource, plane->id());
373 
374     auto &color = dpp.SolidColor();
375     // exynos_win_config_data.color ARGB
376     solidColor = (color.a << 24) | (color.r << 16) | (color.g << 8) | color.b;
377 
378     int ret = 0;
379     if ((ret = setPlaneColorBlob(plane, plane->eotf_lut_property(),
380                 static_cast<uint32_t>(DppBlobs::EOTF),
381                 dpp.EotfLut(), dpp, dppIndex, drmReq, planeChanged) != NO_ERROR)) {
382         HWC_LOGE(mExynosDisplay, "%s: dpp[%d] set oetf blob fail",
383                 __func__, dppIndex);
384         return ret;
385     }
386     if ((ret = setPlaneColorBlob(plane, plane->gammut_matrix_property(),
387                 static_cast<uint32_t>(DppBlobs::GM),
388                 dpp.Gm(), dpp, dppIndex, drmReq, planeChanged) != NO_ERROR)) {
389         HWC_LOGE(mExynosDisplay, "%s: dpp[%d] set GM blob fail",
390                 __func__, dppIndex);
391         return ret;
392     }
393     if ((ret = setPlaneColorBlob(plane, plane->tone_mapping_property(),
394                 static_cast<uint32_t>(DppBlobs::DTM),
395                 dpp.Dtm(), dpp, dppIndex, drmReq, planeChanged) != NO_ERROR)) {
396         HWC_LOGE(mExynosDisplay, "%s: dpp[%d] set DTM blob fail",
397                 __func__, dppIndex);
398         return ret;
399     }
400     if ((ret = setPlaneColorBlob(plane, plane->oetf_lut_property(),
401                 static_cast<uint32_t>(DppBlobs::OETF),
402                 dpp.OetfLut(), dpp, dppIndex, drmReq, planeChanged) != NO_ERROR)) {
403         HWC_LOGE(mExynosDisplay, "%s: dpp[%d] set OETF blob fail",
404                 __func__, dppIndex);
405         return ret;
406     }
407 
408     return 0;
409 }
410 
~SaveBlob()411 ExynosDisplayDrmInterfaceModule::SaveBlob::~SaveBlob()
412 {
413     for (auto &it: blobs) {
414         mDrmDevice->DestroyPropertyBlob(it);
415     }
416     blobs.clear();
417 }
418 
addBlob(uint32_t type,uint32_t blob)419 void ExynosDisplayDrmInterfaceModule::SaveBlob::addBlob(
420         uint32_t type, uint32_t blob)
421 {
422     if (type >= blobs.size()) {
423         ALOGE("Invalid dqe blop type: %d", type);
424         return;
425     }
426     if (blobs[type] > 0)
427         mDrmDevice->DestroyPropertyBlob(blobs[type]);
428 
429     blobs[type] = blob;
430 }
431 
getBlob(uint32_t type)432 uint32_t ExynosDisplayDrmInterfaceModule::SaveBlob::getBlob(uint32_t type)
433 {
434     if (type >= blobs.size()) {
435         ALOGE("Invalid dqe blop type: %d", type);
436         return 0;
437     }
438     return blobs[type];
439 }
440 
getDisplayInfo(std::vector<displaycolor::DisplayInfo> & display_info)441 void ExynosDisplayDrmInterfaceModule::getDisplayInfo(
442         std::vector<displaycolor::DisplayInfo> &display_info) {
443     displaycolor::DisplayInfo primary_display;
444 
445     primary_display.brightness_ranges =
446             mExynosDisplay->mBrightnessController->getBrightnessRanges();
447     primary_display.panel_name = GetPanelName();
448     primary_display.panel_serial = GetPanelSerial();
449 
450     display_info.push_back(primary_display);
451 }
452 
GetPanelInfo(const std::string & sysfs_rel,char delim)453 const std::string ExynosDisplayDrmInterfaceModule::GetPanelInfo(const std::string &sysfs_rel,
454                                                                 char delim) {
455     ExynosPrimaryDisplayModule* display = (ExynosPrimaryDisplayModule*)mExynosDisplay;
456     const DisplayType type = display->getBuiltInDisplayType();
457     const std::string &sysfs = display->getPanelSysfsPath(type);
458 
459     if (sysfs.empty()) {
460         return "";
461     }
462 
463     std::string info;
464     if (readLineFromFile(sysfs + "/" + sysfs_rel, info, delim) != OK) {
465         ALOGE("failed reading %s/%s", sysfs.c_str(), sysfs_rel.c_str());
466         return "";
467     }
468 
469     return info;
470 }
471 
472 /* For Histogram */
createHistoRoiBlob(uint32_t & blobId)473 int32_t ExynosDisplayDrmInterfaceModule::createHistoRoiBlob(uint32_t &blobId) {
474     struct histogram_roi histo_roi;
475 
476     std::unique_lock<std::mutex> lk((mHistogramInfo->mSetHistInfoMutex));
477     histo_roi.start_x = mHistogramInfo->getHistogramROI().start_x;
478     histo_roi.start_y = mHistogramInfo->getHistogramROI().start_y;
479     histo_roi.hsize = mHistogramInfo->getHistogramROI().hsize;
480     histo_roi.vsize = mHistogramInfo->getHistogramROI().vsize;
481 
482     int ret = mDrmDevice->CreatePropertyBlob(&histo_roi, sizeof(histo_roi), &blobId);
483     if (ret) {
484         HWC_LOGE(mExynosDisplay, "Failed to create histogram roi blob %d", ret);
485         return ret;
486     }
487 
488     return NO_ERROR;
489 }
490 
createHistoWeightsBlob(uint32_t & blobId)491 int32_t ExynosDisplayDrmInterfaceModule::createHistoWeightsBlob(uint32_t &blobId) {
492     struct histogram_weights histo_weights;
493 
494     std::unique_lock<std::mutex> lk((mHistogramInfo->mSetHistInfoMutex));
495     histo_weights.weight_r = mHistogramInfo->getHistogramWeights().weight_r;
496     histo_weights.weight_g = mHistogramInfo->getHistogramWeights().weight_g;
497     histo_weights.weight_b = mHistogramInfo->getHistogramWeights().weight_b;
498 
499     int ret = mDrmDevice->CreatePropertyBlob(&histo_weights, sizeof(histo_weights), &blobId);
500     if (ret) {
501         HWC_LOGE(mExynosDisplay, "Failed to create histogram weights blob %d", ret);
502         return ret;
503     }
504 
505     return NO_ERROR;
506 }
507 
setDisplayHistoBlob(const DrmProperty & prop,const uint32_t type,ExynosDisplayDrmInterface::DrmModeAtomicReq & drmReq)508 int32_t ExynosDisplayDrmInterfaceModule::setDisplayHistoBlob(
509         const DrmProperty &prop, const uint32_t type,
510         ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq) {
511     if (!prop.id()) return NO_ERROR;
512 
513     int32_t ret = NO_ERROR;
514     uint32_t blobId = 0;
515 
516     switch (type) {
517         case HistoBlobs::ROI:
518             ret = createHistoRoiBlob(blobId);
519             break;
520         case HistoBlobs::WEIGHTS:
521             ret = createHistoWeightsBlob(blobId);
522             break;
523         default:
524             ret = -EINVAL;
525     }
526     if (ret != NO_ERROR) {
527         HWC_LOGE(mExynosDisplay, "%s: Failed to create blob", __func__);
528         return ret;
529     }
530 
531     /* Skip setting when previous and current setting is same with 0 */
532     if ((blobId == 0) && (mOldHistoBlobs.getBlob(type) == 0)) return ret;
533 
534     if ((ret = drmReq.atomicAddProperty(mDrmCrtc->id(), prop, blobId)) < 0) {
535         HWC_LOGE(mExynosDisplay, "%s: Failed to add property", __func__);
536         return ret;
537     }
538     mOldHistoBlobs.addBlob(type, blobId);
539 
540     return ret;
541 }
542 
setDisplayHistogramSetting(ExynosDisplayDrmInterface::DrmModeAtomicReq & drmReq)543 int32_t ExynosDisplayDrmInterfaceModule::setDisplayHistogramSetting(
544         ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq) {
545     if ((isHistogramInfoRegistered() == false) || (isPrimary() == false)) return NO_ERROR;
546 
547     int ret = NO_ERROR;
548 
549     if ((ret = setDisplayHistoBlob(mDrmCrtc->histogram_roi_property(),
550                                    static_cast<uint32_t>(HistoBlobs::ROI), drmReq) != NO_ERROR)) {
551         HWC_LOGE(mExynosDisplay, "%s: Failed to set Histo_ROI blob", __func__);
552         return ret;
553     }
554     if ((ret = setDisplayHistoBlob(mDrmCrtc->histogram_weights_property(),
555                                    static_cast<uint32_t>(HistoBlobs::WEIGHTS),
556                                    drmReq) != NO_ERROR)) {
557         HWC_LOGE(mExynosDisplay, "%s: Failed to set Histo_Weights blob", __func__);
558         return ret;
559     }
560 
561     const DrmProperty &prop_histo_threshold = mDrmCrtc->histogram_threshold_property();
562     if (prop_histo_threshold.id()) {
563         if ((ret = drmReq.atomicAddProperty(mDrmCrtc->id(), prop_histo_threshold,
564                                             (uint64_t)(mHistogramInfo->getHistogramThreshold()),
565                                             true)) < 0) {
566             HWC_LOGE(mExynosDisplay, "%s: Failed to set histogram thereshold property", __func__);
567             return ret;
568         }
569     }
570 
571     return NO_ERROR;
572 }
573 
setHistogramControl(hidl_histogram_control_t control)574 int32_t ExynosDisplayDrmInterfaceModule::setHistogramControl(hidl_histogram_control_t control) {
575     if ((isHistogramInfoRegistered() == false) || (isPrimary() == false)) return NO_ERROR;
576 
577     int ret = NO_ERROR;
578     uint32_t crtc_id = mDrmCrtc->id();
579 
580     if (control == hidl_histogram_control_t::HISTOGRAM_CONTROL_REQUEST) {
581         ret = mDrmDevice->CallVendorIoctl(DRM_IOCTL_EXYNOS_HISTOGRAM_REQUEST, (void *)&crtc_id);
582     } else if (control == hidl_histogram_control_t::HISTOGRAM_CONTROL_CANCEL) {
583         ret = mDrmDevice->CallVendorIoctl(DRM_IOCTL_EXYNOS_HISTOGRAM_CANCEL, (void *)&crtc_id);
584     }
585 
586     return ret;
587 }
588 
setHistogramData(void * bin)589 int32_t ExynosDisplayDrmInterfaceModule::setHistogramData(void *bin) {
590     if (!bin) return -EINVAL;
591 
592     /*
593      * There are two handling methods.
594      * For ContentSampling in HWC_2.3 API, histogram bin needs to be accumulated.
595      * For Histogram IDL, histogram bin need to be sent to IDL block.
596      */
597     if (mHistogramInfo->getHistogramType() == HistogramInfo::HistogramType::HISTOGRAM_HIDL) {
598         (mHistogramInfo.get())->callbackHistogram((char16_t *)bin);
599     } else {
600         /*
601          * ContentSampling in HWC2.3 API is not supported
602          */
603         return -ENOTSUP;
604     }
605 
606     return NO_ERROR;
607 }
608 
609 //////////////////////////////////////////////////// ExynosPrimaryDisplayDrmInterfaceModule //////////////////////////////////////////////////////////////////
ExynosPrimaryDisplayDrmInterfaceModule(ExynosDisplay * exynosDisplay)610 ExynosPrimaryDisplayDrmInterfaceModule::ExynosPrimaryDisplayDrmInterfaceModule(ExynosDisplay *exynosDisplay)
611 : ExynosDisplayDrmInterfaceModule(exynosDisplay)
612 {
613 }
614 
~ExynosPrimaryDisplayDrmInterfaceModule()615 ExynosPrimaryDisplayDrmInterfaceModule::~ExynosPrimaryDisplayDrmInterfaceModule()
616 {
617 }
618 
619 //////////////////////////////////////////////////// ExynosExternalDisplayDrmInterfaceModule //////////////////////////////////////////////////////////////////
ExynosExternalDisplayDrmInterfaceModule(ExynosDisplay * exynosDisplay)620 ExynosExternalDisplayDrmInterfaceModule::ExynosExternalDisplayDrmInterfaceModule(ExynosDisplay *exynosDisplay)
621 : ExynosDisplayDrmInterfaceModule(exynosDisplay)
622 {
623 }
624 
~ExynosExternalDisplayDrmInterfaceModule()625 ExynosExternalDisplayDrmInterfaceModule::~ExynosExternalDisplayDrmInterfaceModule()
626 {
627 }
628