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