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