1 /*
2 * Copyright (C) 2012 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 "ExynosHWCService.h"
18
19 #include <chrono>
20
21 #include "ExynosExternalDisplay.h"
22 #include "ExynosVirtualDisplay.h"
23 #include "ExynosVirtualDisplayModule.h"
24 #define HWC_SERVICE_DEBUG 0
25
26 namespace android {
27
28 ANDROID_SINGLETON_STATIC_INSTANCE(ExynosHWCService);
29
ExynosHWCService()30 ExynosHWCService::ExynosHWCService() :
31 mHWCService(NULL),
32 mHWCCtx(NULL),
33 bootFinishedCallback(NULL),
34 doPSRExit(NULL)
35 {
36 ALOGD_IF(HWC_SERVICE_DEBUG, "ExynosHWCService Constructor is called");
37 }
38
~ExynosHWCService()39 ExynosHWCService::~ExynosHWCService()
40 {
41 ALOGD_IF(HWC_SERVICE_DEBUG, "ExynosHWCService Destructor is called");
42 }
43
addVirtualDisplayDevice()44 int ExynosHWCService::addVirtualDisplayDevice()
45 {
46 ALOGD_IF(HWC_SERVICE_DEBUG, "%s", __func__);
47
48 mHWCCtx->device->mNumVirtualDisplay++;
49
50 return NO_ERROR;
51 }
52
destroyVirtualDisplayDevice()53 int ExynosHWCService::destroyVirtualDisplayDevice()
54 {
55 ALOGD_IF(HWC_SERVICE_DEBUG, "%s", __func__);
56
57 mHWCCtx->device->mNumVirtualDisplay--;
58
59 return NO_ERROR;
60 }
61
setWFDMode(unsigned int mode)62 int ExynosHWCService::setWFDMode(unsigned int mode)
63 {
64 ALOGD_IF(HWC_SERVICE_DEBUG, "%s::mode=%d", __func__, mode);
65 for (uint32_t i = 0; i < mHWCCtx->device->mDisplays.size(); i++) {
66 if (mHWCCtx->device->mDisplays[i]->mType == HWC_DISPLAY_VIRTUAL) {
67 ExynosVirtualDisplay *virtualdisplay =
68 (ExynosVirtualDisplay *)mHWCCtx->device->mDisplays[i];
69 return virtualdisplay->setWFDMode(mode);
70 }
71 }
72 return INVALID_OPERATION;
73 }
74
getWFDMode()75 int ExynosHWCService::getWFDMode()
76 {
77 ALOGD_IF(HWC_SERVICE_DEBUG, "%s", __func__);
78 for (uint32_t i = 0; i < mHWCCtx->device->mDisplays.size(); i++) {
79 if (mHWCCtx->device->mDisplays[i]->mType == HWC_DISPLAY_VIRTUAL) {
80 ExynosVirtualDisplay *virtualdisplay =
81 (ExynosVirtualDisplay *)mHWCCtx->device->mDisplays[i];
82 return virtualdisplay->getWFDMode();
83 }
84 }
85 return INVALID_OPERATION;
86 }
87
sendWFDCommand(int32_t cmd,int32_t ext1,int32_t ext2)88 int ExynosHWCService::sendWFDCommand(int32_t cmd, int32_t ext1, int32_t ext2)
89 {
90 ALOGD_IF(HWC_SERVICE_DEBUG, "%s::cmd=%d, ext1=%d, ext2=%d", __func__, cmd, ext1, ext2);
91 for (uint32_t i = 0; i < mHWCCtx->device->mDisplays.size(); i++) {
92 if (mHWCCtx->device->mDisplays[i]->mType == HWC_DISPLAY_VIRTUAL) {
93 ExynosVirtualDisplay *virtualdisplay =
94 (ExynosVirtualDisplay *)mHWCCtx->device->mDisplays[i];
95 return virtualdisplay->sendWFDCommand(cmd, ext1, ext2);
96 }
97 }
98 return INVALID_OPERATION;
99 }
100
setSecureVDSMode(unsigned int mode)101 int ExynosHWCService::setSecureVDSMode(unsigned int mode)
102 {
103 ALOGD_IF(HWC_SERVICE_DEBUG, "%s::mode=%d", __func__, mode);
104 for (uint32_t i = 0; i < mHWCCtx->device->mDisplays.size(); i++) {
105 if (mHWCCtx->device->mDisplays[i]->mType == HWC_DISPLAY_VIRTUAL) {
106 ExynosVirtualDisplay *virtualdisplay =
107 (ExynosVirtualDisplay *)mHWCCtx->device->mDisplays[i];
108 return virtualdisplay->setSecureVDSMode(mode);
109 }
110 }
111 return INVALID_OPERATION;
112 }
113
setWFDOutputResolution(unsigned int width,unsigned int height)114 int ExynosHWCService::setWFDOutputResolution(unsigned int width, unsigned int height)
115 {
116 ALOGD_IF(HWC_SERVICE_DEBUG, "%s::width=%d, height=%d", __func__, width, height);
117
118 for (uint32_t i = 0; i < mHWCCtx->device->mDisplays.size(); i++) {
119 if (mHWCCtx->device->mDisplays[i]->mType == HWC_DISPLAY_VIRTUAL) {
120 ExynosVirtualDisplay *virtualdisplay =
121 (ExynosVirtualDisplay *)mHWCCtx->device->mDisplays[i];
122 return virtualdisplay->setWFDOutputResolution(width, height);
123 }
124 }
125 return INVALID_OPERATION;
126 }
127
getWFDOutputResolution(unsigned int * width,unsigned int * height)128 void ExynosHWCService::getWFDOutputResolution(unsigned int *width, unsigned int *height)
129 {
130 ALOGD_IF(HWC_SERVICE_DEBUG, "%s", __func__);
131 for (uint32_t i = 0; i < mHWCCtx->device->mDisplays.size(); i++) {
132 if (mHWCCtx->device->mDisplays[i]->mType == HWC_DISPLAY_VIRTUAL) {
133 ExynosVirtualDisplay *virtualdisplay =
134 (ExynosVirtualDisplay *)mHWCCtx->device->mDisplays[i];
135 virtualdisplay->getWFDOutputResolution(width, height);
136 return;
137 }
138 }
139 }
140
setPresentationMode(bool use)141 void ExynosHWCService::setPresentationMode(bool use)
142 {
143 ALOGD_IF(HWC_SERVICE_DEBUG, "%s::PresentationMode=%s", __func__, use == false ? "false" : "true");
144 for (uint32_t i = 0; i < mHWCCtx->device->mDisplays.size(); i++) {
145 if (mHWCCtx->device->mDisplays[i]->mType == HWC_DISPLAY_VIRTUAL) {
146 ExynosVirtualDisplay *virtualdisplay =
147 (ExynosVirtualDisplay *)mHWCCtx->device->mDisplays[i];
148 virtualdisplay->setPresentationMode(!!use);
149 return;
150 }
151 }
152 }
153
getPresentationMode()154 int ExynosHWCService::getPresentationMode()
155 {
156 ALOGD_IF(HWC_SERVICE_DEBUG, "%s", __func__);
157 for (uint32_t i = 0; i < mHWCCtx->device->mDisplays.size(); i++) {
158 if (mHWCCtx->device->mDisplays[i]->mType == HWC_DISPLAY_VIRTUAL) {
159 ExynosVirtualDisplay *virtualdisplay =
160 (ExynosVirtualDisplay *)mHWCCtx->device->mDisplays[i];
161 return virtualdisplay->getPresentationMode();
162 }
163 }
164 return INVALID_OPERATION;
165 }
166
setVDSGlesFormat(int format)167 int ExynosHWCService::setVDSGlesFormat(int format)
168 {
169 ALOGD_IF(HWC_SERVICE_DEBUG, "%s::format=%d", __func__, format);
170
171 for (uint32_t i = 0; i < mHWCCtx->device->mDisplays.size(); i++) {
172 if (mHWCCtx->device->mDisplays[i]->mType == HWC_DISPLAY_VIRTUAL) {
173 ExynosVirtualDisplay *virtualdisplay =
174 (ExynosVirtualDisplay *)mHWCCtx->device->mDisplays[i];
175 return virtualdisplay->setVDSGlesFormat(format);
176 }
177 }
178
179 return INVALID_OPERATION;
180 }
181
getExternalDisplayConfigs()182 int ExynosHWCService::getExternalDisplayConfigs()
183 {
184 ALOGD_IF(HWC_SERVICE_DEBUG, "%s", __func__);
185
186 ExynosExternalDisplay *external_display =
187 (ExynosExternalDisplay *)mHWCCtx->device->getDisplay(getDisplayId(HWC_DISPLAY_EXTERNAL, 0));
188
189 if ((external_display != nullptr) &&
190 (external_display->mHpdStatus == true)) {
191 external_display->mDisplayInterface->dumpDisplayConfigs();
192 }
193
194 return NO_ERROR;
195 }
196
setExternalDisplayConfig(unsigned int index)197 int ExynosHWCService::setExternalDisplayConfig(unsigned int index)
198 {
199 ALOGD_IF(HWC_SERVICE_DEBUG, "%s::config=%d", __func__, index);
200
201 ExynosExternalDisplay *external_display =
202 (ExynosExternalDisplay *)mHWCCtx->device->getDisplay(getDisplayId(HWC_DISPLAY_EXTERNAL, 0));
203
204 if ((external_display != nullptr) &&
205 (external_display->mHpdStatus == true)) {
206 external_display->setActiveConfig(index);
207 }
208
209 return NO_ERROR;
210 }
211
setExternalVsyncEnabled(unsigned int index)212 int ExynosHWCService::setExternalVsyncEnabled(unsigned int index)
213 {
214 ALOGD_IF(HWC_SERVICE_DEBUG, "%s::config=%d", __func__, index);
215
216 mHWCCtx->device->mVsyncDisplayId = index;
217 ExynosExternalDisplay *external_display =
218 (ExynosExternalDisplay *)mHWCCtx->device->getDisplay(getDisplayId(HWC_DISPLAY_EXTERNAL, 0));
219 if (external_display != nullptr)
220 external_display->setVsyncEnabled(index);
221
222 return NO_ERROR;
223 }
224
getExternalHdrCapabilities()225 int ExynosHWCService::getExternalHdrCapabilities()
226 {
227 ALOGD_IF(HWC_SERVICE_DEBUG, "%s", __func__);
228
229 ExynosExternalDisplay *external_display =
230 (ExynosExternalDisplay *)mHWCCtx->device->getDisplay(getDisplayId(HWC_DISPLAY_EXTERNAL, 0));
231
232 if (external_display != nullptr)
233 return external_display->mExternalHdrSupported;
234 return 0;
235 }
236
setBootFinishedCallback(void (* callback)(ExynosHWCCtx *))237 void ExynosHWCService::setBootFinishedCallback(void (*callback)(ExynosHWCCtx *))
238 {
239 ALOGD_IF(HWC_SERVICE_DEBUG, "%s, callback %p", __func__, callback);
240 bootFinishedCallback = callback;
241 }
242
setBootFinished()243 void ExynosHWCService::setBootFinished() {
244 ALOGD_IF(HWC_SERVICE_DEBUG, "%s", __func__);
245 if (bootFinishedCallback != NULL)
246 bootFinishedCallback(mHWCCtx);
247 }
248
enableMPP(uint32_t physicalType,uint32_t physicalIndex,uint32_t logicalIndex,uint32_t enable)249 void ExynosHWCService::enableMPP(uint32_t physicalType, uint32_t physicalIndex, uint32_t logicalIndex, uint32_t enable)
250 {
251 ALOGD("%s:: type(%d), index(%d, %d), enable(%d)",
252 __func__, physicalType, physicalIndex, logicalIndex, enable);
253 ExynosResourceManager::enableMPP(physicalType, physicalIndex, logicalIndex, enable);
254 mHWCCtx->device->setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
255 mHWCCtx->device->invalidate();
256 }
257
setScaleDownRatio(uint32_t physicalType,uint32_t physicalIndex,uint32_t logicalIndex,uint32_t scaleDownRatio)258 void ExynosHWCService::setScaleDownRatio(uint32_t physicalType,
259 uint32_t physicalIndex, uint32_t logicalIndex, uint32_t scaleDownRatio)
260 {
261 ALOGD("%s:: type(%d), index(%d, %d), scaleDownRatio(%d)",
262 __func__, physicalType, physicalIndex, logicalIndex, scaleDownRatio);
263 ExynosResourceManager::setScaleDownRatio(physicalType, physicalIndex, logicalIndex, scaleDownRatio);
264 mHWCCtx->device->setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
265 mHWCCtx->device->invalidate();
266 }
267
setLbeCtrl(uint32_t display_id,uint32_t state,uint32_t lux)268 void ExynosHWCService::setLbeCtrl(uint32_t display_id, uint32_t state, uint32_t lux) {
269 ALOGD("%s:: display_id(%d), state(%d), lux(%d)", __func__, display_id, state, lux);
270 if (mHWCCtx) {
271 auto display = mHWCCtx->device->getDisplay(display_id);
272
273 if (display != nullptr) {
274 display->setLbeState(static_cast<LbeState>(state));
275 display->setLbeAmbientLight(lux);
276 }
277 }
278 }
279
setHWCDebug(int debug)280 void ExynosHWCService::setHWCDebug(int debug)
281 {
282 ALOGD_IF(HWC_SERVICE_DEBUG, "%s, debug %d", __func__, debug);
283 mHWCCtx->device->setHWCDebug(debug);
284 }
285
getHWCDebug()286 uint32_t ExynosHWCService::getHWCDebug()
287 {
288 ALOGD_IF(HWC_SERVICE_DEBUG, "%s", __func__);
289 return mHWCCtx->device->getHWCDebug();
290 }
291
setHWCFenceDebug(uint32_t fenceNum,uint32_t ipNum,uint32_t mode)292 void ExynosHWCService::setHWCFenceDebug(uint32_t fenceNum, uint32_t ipNum, uint32_t mode)
293 {
294 ALOGD_IF(HWC_SERVICE_DEBUG, "%s", __func__);
295 mHWCCtx->device->setHWCFenceDebug(fenceNum, ipNum, mode);
296 }
297
getHWCFenceDebug()298 void ExynosHWCService::getHWCFenceDebug()
299 {
300 ALOGD_IF(HWC_SERVICE_DEBUG, "%s", __func__);
301 mHWCCtx->device->getHWCFenceDebug();
302 }
303
setHWCCtl(uint32_t display,uint32_t ctrl,int32_t val)304 int ExynosHWCService::setHWCCtl(uint32_t display, uint32_t ctrl, int32_t val)
305 {
306 int err = 0;
307 switch (ctrl) {
308 case HWC_CTL_FORCE_GPU:
309 case HWC_CTL_WINDOW_UPDATE:
310 case HWC_CTL_FORCE_PANIC:
311 case HWC_CTL_SKIP_STATIC:
312 case HWC_CTL_SKIP_M2M_PROCESSING:
313 case HWC_CTL_SKIP_RESOURCE_ASSIGN:
314 case HWC_CTL_SKIP_VALIDATE:
315 case HWC_CTL_DUMP_MID_BUF:
316 case HWC_CTL_CAPTURE_READBACK:
317 case HWC_CTL_ENABLE_COMPOSITION_CROP:
318 case HWC_CTL_ENABLE_EXYNOSCOMPOSITION_OPT:
319 case HWC_CTL_ENABLE_CLIENTCOMPOSITION_OPT:
320 case HWC_CTL_USE_MAX_G2D_SRC:
321 case HWC_CTL_ENABLE_HANDLE_LOW_FPS:
322 case HWC_CTL_ENABLE_EARLY_START_MPP:
323 case HWC_CTL_DISPLAY_MODE:
324 case HWC_CTL_DDI_RESOLUTION_CHANGE:
325 case HWC_CTL_ENABLE_FENCE_TRACER:
326 case HWC_CTL_SYS_FENCE_LOGGING:
327 case HWC_CTL_DO_FENCE_FILE_DUMP:
328 ALOGI("%s::%d on/off=%d", __func__, ctrl, val);
329 mHWCCtx->device->setHWCControl(display, ctrl, val);
330 break;
331 default:
332 ALOGE("%s: unsupported HWC_CTL, (%d)", __func__, ctrl);
333 err = -1;
334 break;
335 }
336 return err;
337 }
338
setDDIScaler(uint32_t width,uint32_t height)339 int ExynosHWCService::setDDIScaler(uint32_t width, uint32_t height)
340 {
341 ALOGD_IF(HWC_SERVICE_DEBUG, "%s, width=%d, height=%d", __func__, width, height);
342 if (mHWCCtx) {
343 ExynosDisplay *display = (ExynosDisplay*)mHWCCtx->device->getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
344
345 if (display == NULL)
346 return -EINVAL;
347
348 display->setDDIScalerEnable(width, height);
349 return NO_ERROR;
350 } else {
351 ALOGE_IF(HWC_SERVICE_DEBUG, "Service is not exist");
352 return -EINVAL;
353 }
354 }
355
356 #if 0
357 void ExynosHWCService::setPSRExitCallback(void (*callback)(exynos_hwc_composer_device_1_t *))
358 {
359 ALOGD_IF(HWC_SERVICE_DEBUG, "%s, callback %p", __func__, callback);
360 doPSRExit = callback;
361 }
362
363 void ExynosHWCService::notifyPSRExit()
364 {
365 ALOGD_IF(HWC_SERVICE_DEBUG, "%s, doPSRExit %p", __func__, doPSRExit);
366 if (doPSRExit != NULL) {
367 ALOGD_IF(HWC_SERVICE_DEBUG, "%s, line %d", __func__, __LINE__);
368 doPSRExit(mHWCCtx);
369 }
370 ALOGD_IF(HWC_SERVICE_DEBUG, "%s, line %d", __func__, __LINE__);
371 }
372
373 #endif
374
createServiceLocked()375 int ExynosHWCService::createServiceLocked()
376 {
377 ALOGD_IF(HWC_SERVICE_DEBUG, "%s::", __func__);
378 sp<IServiceManager> sm = defaultServiceManager();
379 sm->addService(String16("Exynos.HWCService"), mHWCService, false);
380 if (sm->checkService(String16("Exynos.HWCService")) != NULL) {
381 ALOGD_IF(HWC_SERVICE_DEBUG, "adding Exynos.HWCService succeeded");
382 return 0;
383 } else {
384 ALOGE_IF(HWC_SERVICE_DEBUG, "adding Exynos.HWCService failed");
385 return -1;
386 }
387 }
388
getExynosHWCService()389 ExynosHWCService *ExynosHWCService::getExynosHWCService()
390 {
391 ALOGD_IF(HWC_SERVICE_DEBUG, "%s::", __func__);
392 ExynosHWCService& instance = ExynosHWCService::getInstance();
393 Mutex::Autolock _l(instance.mLock);
394 if (instance.mHWCService == NULL) {
395 instance.mHWCService = &instance;
396 int status = ExynosHWCService::getInstance().createServiceLocked();
397 if (status != 0) {
398 ALOGE_IF(HWC_SERVICE_DEBUG, "getExynosHWCService failed");
399 }
400 }
401 return instance.mHWCService;
402 }
403
setExynosHWCCtx(ExynosHWCCtx * HWCCtx)404 void ExynosHWCService::setExynosHWCCtx(ExynosHWCCtx *HWCCtx)
405 {
406 ALOGD_IF(HWC_SERVICE_DEBUG, "%s, HWCCtx=%p", __func__, HWCCtx);
407 if(HWCCtx) {
408 mHWCCtx = HWCCtx;
409 }
410 }
411
setDisplayDeviceMode(int32_t display_id,int32_t mode)412 int32_t ExynosHWCService::setDisplayDeviceMode(int32_t display_id, int32_t mode)
413 {
414 return mHWCCtx->device->setDisplayDeviceMode(display_id, mode);
415 }
416
setPanelGammaTableSource(int32_t display_id,int32_t type,int32_t source)417 int32_t ExynosHWCService::setPanelGammaTableSource(int32_t display_id, int32_t type,
418 int32_t source) {
419 return mHWCCtx->device->setPanelGammaTableSource(display_id, type, source);
420 }
421
setDisplayBrightness(int32_t display_id,float brightness)422 int32_t ExynosHWCService::setDisplayBrightness(int32_t display_id, float brightness) {
423 if (brightness < 0 || brightness > 1.0)
424 return -EINVAL;
425
426 auto display = mHWCCtx->device->getDisplay(display_id);
427
428 if (display != nullptr)
429 return display->setDisplayBrightness(brightness);
430
431 return -EINVAL;
432 }
433
setDisplayLhbm(int32_t display_id,uint32_t on)434 int32_t ExynosHWCService::setDisplayLhbm(int32_t display_id, uint32_t on) {
435 if (on > 1) return -EINVAL;
436
437 auto display = mHWCCtx->device->getDisplay(display_id);
438
439 if (display != nullptr) {
440 display->requestLhbm(!!on);
441 return NO_ERROR;
442 }
443
444 return -EINVAL;
445 }
446
setMinIdleRefreshRate(uint32_t display_id,int32_t fps)447 int32_t ExynosHWCService::setMinIdleRefreshRate(uint32_t display_id, int32_t fps) {
448 ALOGD("ExynosHWCService::%s() display_id(%u) fps(%d)", __func__, display_id, fps);
449
450 auto display = mHWCCtx->device->getDisplay(display_id);
451
452 if (display != nullptr) {
453 return display->setMinIdleRefreshRate(fps);
454 }
455
456 return -EINVAL;
457 }
458
setRefreshRateThrottle(uint32_t display_id,int32_t delayMs)459 int32_t ExynosHWCService::setRefreshRateThrottle(uint32_t display_id, int32_t delayMs) {
460 ALOGD("ExynosHWCService::%s() display_id(%u) delayMs(%d)", __func__, display_id, delayMs);
461
462 auto display = mHWCCtx->device->getDisplay(display_id);
463
464 if (display != nullptr) {
465 return display->setRefreshRateThrottleNanos(
466 std::chrono::duration_cast<std::chrono::nanoseconds>(
467 std::chrono::milliseconds(delayMs))
468 .count());
469 }
470
471 return -EINVAL;
472 }
473
474 } //namespace android
475