libhwjpeg: resolve compilation errors
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos.git] / libvpphdmi / ExynosExternalDisplay.cpp
CommitLineData
5763fb39
T
1//#define LOG_NDEBUG 0
2#include "ExynosHWC.h"
3#include "ExynosHWCUtils.h"
4#include "ExynosMPPModule.h"
5#include "ExynosExternalDisplay.h"
6#include "ExynosSecondaryDisplayModule.h"
7#include "decon_tv.h"
8#include <errno.h>
9
10extern struct v4l2_dv_timings dv_timings[];
11bool is_same_dv_timings(const struct v4l2_dv_timings *t1,
12 const struct v4l2_dv_timings *t2)
13{
14 if (t1->type == t2->type &&
15 t1->bt.width == t2->bt.width &&
16 t1->bt.height == t2->bt.height &&
17 t1->bt.interlaced == t2->bt.interlaced &&
18 t1->bt.polarities == t2->bt.polarities &&
19 t1->bt.pixelclock == t2->bt.pixelclock &&
20 t1->bt.hfrontporch == t2->bt.hfrontporch &&
21 t1->bt.vfrontporch == t2->bt.vfrontporch &&
22 t1->bt.vsync == t2->bt.vsync &&
23 t1->bt.vbackporch == t2->bt.vbackporch &&
24 (!t1->bt.interlaced ||
25 (t1->bt.il_vfrontporch == t2->bt.il_vfrontporch &&
26 t1->bt.il_vsync == t2->bt.il_vsync &&
27 t1->bt.il_vbackporch == t2->bt.il_vbackporch)))
28 return true;
29 return false;
30}
31
32int ExynosExternalDisplay::getDVTimingsIndex(int preset)
33{
34 for (int i = 0; i < SUPPORTED_DV_TIMINGS_NUM; i++) {
35 if (preset == preset_index_mappings[i].preset)
36 return preset_index_mappings[i].dv_timings_index;
37 }
38 return -1;
39}
40
41ExynosExternalDisplay::ExynosExternalDisplay(struct exynos5_hwc_composer_device_1_t *pdev)
42 : ExynosDisplay(EXYNOS_EXTERNAL_DISPLAY, pdev),
43 mEnabled(false),
44 mBlanked(false),
45 mUseSubtitles(false),
46 mReserveMemFd(-1),
47 mDRMTempBuffer(NULL),
48 mFlagIONBufferAllocated(false)
49{
50 mXres = 0;
51 mYres = 0;
52 mXdpi = 0;
53 mYdpi = 0;
54 mVsyncPeriod = 0;
55 mInternalDMAs.add(IDMA_G3);
56 mReserveMemFd = open(HDMI_RESERVE_MEM_DEV_NAME, O_RDWR);
57 if (mReserveMemFd < 0)
58 ALOGE("Fail to open hdmi_reserve_mem_fd %s, error(%d)", HDMI_RESERVE_MEM_DEV_NAME, mReserveMemFd);
59 else
60 ALOGI("Open %s", HDMI_RESERVE_MEM_DEV_NAME);
61}
62
63ExynosExternalDisplay::~ExynosExternalDisplay()
64{
65 if (mDRMTempBuffer != NULL) {
66 mAllocDevice->free(mAllocDevice, mDRMTempBuffer);
67 mDRMTempBuffer = NULL;
68 }
69 if (mReserveMemFd > 0)
70 close(mReserveMemFd);
71}
72
73void ExynosExternalDisplay::allocateLayerInfos(hwc_display_contents_1_t* contents)
74{
75 ExynosDisplay::allocateLayerInfos(contents);
76}
77
78int ExynosExternalDisplay::prepare(hwc_display_contents_1_t* contents)
79{
80 ExynosDisplay::prepare(contents);
81 return 0;
82}
83
84int ExynosExternalDisplay::postMPPM2M(hwc_layer_1_t &layer, struct decon_win_config *config, int win_map, int index)
85{
86 int err = 0;
87 private_handle_t *handle = private_handle_t::dynamicCast(layer.handle);
88
89 if ((mHasDrmSurface == true) & (getDrmMode(handle->flags) != NO_DRM)) {
90 if (checkIONBufferPrepared() == false) {
91 ALOGV("skip DRM video");
92 handle->flags &= ~GRALLOC_USAGE_VIDEO_EXT;
93 err = configureDRMSkipHandle(config[win_map]);
94 config[win_map].idma_type = (decon_idma_type)mLayerInfos[index]->mDmaType;
95 if (layer.acquireFenceFd >= 0)
96 close(layer.acquireFenceFd);
97 layer.acquireFenceFd = -1;
98 layer.releaseFenceFd = -1;
99 return err;
100 } else {
101 handle->flags |= GRALLOC_USAGE_VIDEO_EXT;
102 }
103 }
104
105 return ExynosDisplay::postMPPM2M(layer, config, win_map, index);
106}
107
108void ExynosExternalDisplay::handleStaticLayers(hwc_display_contents_1_t *contents, struct decon_win_config_data &win_data, int __unused tot_ovly_wins)
109{
110 int win_map = 0;
111 if (mLastFbWindow >= NUM_HW_WINDOWS - 1) {
112 ALOGE("handleStaticLayers:: invalid mLastFbWindow(%d)", mLastFbWindow);
113 return;
114 }
115 win_map = mLastFbWindow + 1;
116 ALOGV("[USE] SKIP_STATIC_LAYER_COMP, mLastFbWindow(%d), win_map(%d)\n", mLastFbWindow, win_map);
117
118 memcpy(&win_data.config[win_map],
119 &mLastConfigData.config[win_map], sizeof(struct decon_win_config));
120 win_data.config[win_map].fence_fd = -1;
121
122 for (size_t i = mFirstFb; i <= mLastFb; i++) {
123 hwc_layer_1_t &layer = contents->hwLayers[i];
124 if (layer.compositionType == HWC_OVERLAY) {
125 ALOGV("[SKIP_STATIC_LAYER_COMP] %d layer.handle: 0x%p, layer.acquireFenceFd: %d\n", i, layer.handle, layer.acquireFenceFd);
126 if (layer.acquireFenceFd >= 0)
127 close(layer.acquireFenceFd);
128 layer.acquireFenceFd = -1;
129 layer.releaseFenceFd = -1;
130 }
131 }
132}
133
134int ExynosExternalDisplay::postFrame(hwc_display_contents_1_t* contents)
135{
136 struct decon_win_config_data win_data;
137 struct decon_win_config *config = win_data.config;
138 int win_map = 0;
139 int tot_ovly_wins = 0;
140 bool hdmiDisabled = false;
141
142 memset(mLastHandles, 0, sizeof(mLastHandles));
143 memset(mLastMPPMap, 0, sizeof(mLastMPPMap));
144 memset(config, 0, sizeof(win_data.config));
145
146 for (size_t i = 0; i < NUM_HW_WINDOWS; i++) {
147 config[i].fence_fd = -1;
148 mLastMPPMap[i].internal_mpp.type = -1;
149 mLastMPPMap[i].external_mpp.type = -1;
150 }
151
152 for (size_t i = 0; i < contents->numHwLayers; i++) {
153 hwc_layer_1_t &layer = contents->hwLayers[i];
154 private_handle_t *handle = NULL;
155 if (layer.handle != NULL)
156 handle = private_handle_t::dynamicCast(layer.handle);
157 // window 0 is background layer
158 size_t window_index = mLayerInfos[i]->mWindowIndex + 1;
159
160 if ((layer.flags & HWC_SKIP_RENDERING) &&
161 ((handle == NULL) || (getDrmMode(handle->flags) == NO_DRM))) {
162 if (layer.acquireFenceFd >= 0)
163 close(layer.acquireFenceFd);
164 layer.acquireFenceFd = -1;
165 layer.releaseFenceFd = -1;
166 continue;
167 }
168
169 if ((layer.compositionType == HWC_OVERLAY) ||
170 (mFbNeeded == true && layer.compositionType == HWC_FRAMEBUFFER_TARGET)) {
171 mLastHandles[window_index] = layer.handle;
172
173 if (handle == NULL) {
174 if (layer.acquireFenceFd >= 0)
175 close(layer.acquireFenceFd);
176 layer.acquireFenceFd = -1;
177 layer.releaseFenceFd = -1;
178 continue;
179 }
180
181 if (getDrmMode(handle->flags) == SECURE_DRM)
182 config[window_index].protection = 1;
183 else
184 config[window_index].protection = 0;
185
186 if ((int)i == mForceOverlayLayerIndex &&
187 mHwc->mS3DMode != S3D_MODE_DISABLED && mHwc->mHdmiResolutionChanged) {
188 if (isPresetSupported(mHwc->mHdmiPreset)) {
189 mHwc->mS3DMode = S3D_MODE_RUNNING;
190 setPreset(mHwc->mHdmiPreset);
191 /*
192 * HDMI was disabled by setPreset
193 * This frame will be handled from next frame
194 */
195 if (layer.acquireFenceFd >= 0)
196 close(layer.acquireFenceFd);
197 layer.acquireFenceFd = -1;
198 layer.releaseFenceFd = -1;
199 layer.flags = HWC_SKIP_RENDERING;
200 hdmiDisabled = true;
201 continue;
202 } else {
203 mHwc->mS3DMode = S3D_MODE_RUNNING;
204 mHwc->mHdmiResolutionChanged = false;
205 mHwc->mHdmiResolutionHandled = true;
206 }
207 }
208 if (mLayerInfos[i]->mInternalMPP != NULL) {
209 mLastMPPMap[window_index].internal_mpp.type = mLayerInfos[i]->mInternalMPP->mType;
210 mLastMPPMap[window_index].internal_mpp.index = mLayerInfos[i]->mInternalMPP->mIndex;
211 }
212 if (mLayerInfos[i]->mExternalMPP != NULL) {
213 mLastMPPMap[window_index].external_mpp.type = mLayerInfos[i]->mExternalMPP->mType;
214 mLastMPPMap[window_index].external_mpp.index = mLayerInfos[i]->mExternalMPP->mIndex;
215 if ((int)i == mForceOverlayLayerIndex && mHwc->mS3DMode == S3D_MODE_RUNNING) {
216 if (isPresetSupported(mHwc->mHdmiPreset)) {
217 mLayerInfos[i]->mExternalMPP->mS3DMode = S3D_NONE;
218 } else {
219 int S3DFormat = getS3DFormat(mHwc->mHdmiPreset);
220 if (S3DFormat == S3D_SBS)
221 mLayerInfos[i]->mExternalMPP->mS3DMode = S3D_SBS;
222 else if (S3DFormat == S3D_TB)
223 mLayerInfos[i]->mExternalMPP->mS3DMode = S3D_TB;
224 }
225 }
226 if (postMPPM2M(layer, config, window_index, i) < 0)
227 continue;
228 } else {
229 configureOverlay(&layer, i, config[window_index]);
230 }
231 }
232 if (window_index == 0 && config[window_index].blending != DECON_BLENDING_NONE) {
233 ALOGV("blending not supported on window 0; forcing BLENDING_NONE");
234 config[window_index].blending = DECON_BLENDING_NONE;
235 }
236 }
237
238 for (size_t i = 0; i < NUM_HW_WINDOWS; i++) {
239 ALOGV("external display: window %u configuration:", i);
240 dumpConfig(config[i]);
241 }
242
243 if (hdmiDisabled) {
244 for (size_t i = 0; i < contents->numHwLayers; i++) {
245 hwc_layer_1_t &layer = contents->hwLayers[i];
246 if (layer.acquireFenceFd >= 0)
247 close(layer.acquireFenceFd);
248 layer.acquireFenceFd = -1;
249 layer.releaseFenceFd = -1;
250 }
251 return 0;
252 }
253
254 if (this->mVirtualOverlayFlag) {
255 handleStaticLayers(contents, win_data, tot_ovly_wins);
256 }
257
258 if (contents->numHwLayers == 1) {
259 hwc_layer_1_t &layer = contents->hwLayers[0];
260 if (layer.acquireFenceFd >= 0)
261 close(layer.acquireFenceFd);
262 layer.acquireFenceFd = -1;
263 layer.releaseFenceFd = -1;
264 }
265
266 if (checkConfigChanged(win_data, mLastConfigData) == false)
267 {
268 for (size_t i = 0; i < contents->numHwLayers; i++) {
269 hwc_layer_1_t &layer = contents->hwLayers[i];
270 size_t window_index = mLayerInfos[i]->mWindowIndex;
271
272 if ((layer.compositionType == HWC_OVERLAY) ||
273 (layer.compositionType == HWC_FRAMEBUFFER_TARGET)) {
274 if (layer.acquireFenceFd >= 0)
275 close(layer.acquireFenceFd);
276
277 if (mLayerInfos[i]->mExternalMPP != NULL) {
278 mLayerInfos[i]->mExternalMPP->mCurrentBuf = (mLayerInfos[i]->mExternalMPP->mCurrentBuf + 1) % mLayerInfos[i]->mExternalMPP->mNumAvailableDstBuffers;
279 }
280 }
281 }
282 return 0;
283 }
284
285 int ret = ioctl(this->mDisplayFd, S3CFB_WIN_CONFIG, &win_data);
286 for (size_t i = 0; i < NUM_HW_WINDOWS; i++)
287 if (config[i].fence_fd != -1)
288 close(config[i].fence_fd);
289 if (ret < 0) {
290 ALOGE("ioctl S3CFB_WIN_CONFIG failed: %s", strerror(errno));
291 return ret;
292 }
293
294 memcpy(&(this->mLastConfigData), &win_data, sizeof(win_data));
295
296 if (!this->mVirtualOverlayFlag)
297 this->mLastFbWindow = mFbWindow;
298
299 if ((mYuvLayers != 0) && (mDRMTempBuffer != NULL)) {
300 mAllocDevice->free(mAllocDevice, mDRMTempBuffer);
301 mDRMTempBuffer = NULL;
302 }
303 return win_data.fence;
304}
305
306int ExynosExternalDisplay::set(hwc_display_contents_1_t* contents)
307{
308 int err = 0;
309 bool drm_skipped = false;
310
311 if (!mEnabled || mBlanked) {
312 for (size_t i = 0; i < contents->numHwLayers; i++) {
313 hwc_layer_1_t &layer = contents->hwLayers[i];
314 if (layer.acquireFenceFd >= 0) {
315 close(layer.acquireFenceFd);
316 layer.acquireFenceFd = -1;
317 }
318 }
319 return 0;
320 }
321
322 if ((mHasDrmSurface == true) && (mForceOverlayLayerIndex != -1) &&
323 (mLayerInfos[mForceOverlayLayerIndex]->mExternalMPP != NULL)) {
324 hwc_layer_1_t &layer = contents->hwLayers[mForceOverlayLayerIndex];
325 if (mFlagIONBufferAllocated == false) {
326 layer.flags |= HWC_SKIP_RENDERING;
327 drm_skipped = true;
328 } else {
329 layer.flags &= ~(HWC_SKIP_RENDERING);
330 }
331 }
332 err = ExynosDisplay::set(contents);
333
334 /* HDMI was disabled to change S3D mode */
335 if (mEnabled == false)
336 return 0;
337
338 /* Restore flags */
339 if (drm_skipped) {
340 if ((mHasDrmSurface == true) && (mForceOverlayLayerIndex != -1) &&
341 (mLayerInfos[mForceOverlayLayerIndex]->mExternalMPP != NULL)) {
342 hwc_layer_1_t &layer = contents->hwLayers[mForceOverlayLayerIndex];
343 layer.flags &= ~(HWC_SKIP_RENDERING);
344 }
345 }
346
347 if (this->mYuvLayers == 0 && !mHwc->local_external_display_pause) {
348 if (mHwc->mS3DMode == S3D_MODE_RUNNING && contents->numHwLayers > 1) {
349 int preset = convert3DTo2D(mHwc->mHdmiCurrentPreset);
350 if (isPresetSupported(preset)) {
351 ALOGI("S3D video is removed, Set Resolution(%d)", preset);
352 setPreset(preset);
353 mHwc->mS3DMode = S3D_MODE_STOPPING;
354 mHwc->mHdmiPreset = preset;
355 if (mHwc->procs)
356 mHwc->procs->invalidate(mHwc->procs);
357 } else {
358 ALOGI("S3D video is removed, Resolution(%d) is not supported. mHdmiCurrentPreset(%d)", preset, mHwc->mHdmiCurrentPreset);
359 mHwc->mS3DMode = S3D_MODE_DISABLED;
360 mHwc->mHdmiPreset = mHwc->mHdmiCurrentPreset;
361 }
362 }
363 }
364
365 return err;
366}
367
368void ExynosExternalDisplay::determineYuvOverlay(hwc_display_contents_1_t *contents)
369{
370 mForceOverlayLayerIndex = -1;
371 mHasDrmSurface = false;
372 mYuvLayers = 0;
373 bool useVPPOverlayFlag = false;
374
375 for (size_t i = 0; i < contents->numHwLayers; i++) {
376 ExynosMPPModule* supportedInternalMPP = NULL;
377 ExynosMPPModule* supportedExternalMPP = NULL;
378
379 hwc_layer_1_t &layer = contents->hwLayers[i];
380 useVPPOverlayFlag = false;
381 if (layer.handle) {
382 private_handle_t *handle = private_handle_t::dynamicCast(layer.handle);
383
384 if (getDrmMode(handle->flags) != NO_DRM)
385 useVPPOverlayFlag = true;
386#if defined(GSC_VIDEO)
387 /* check yuv surface */
388 if (!mForceFb && !isFormatRgb(handle->format)) {
389 if (isOverlaySupported(contents->hwLayers[i], i, useVPPOverlayFlag, &supportedInternalMPP, &supportedExternalMPP)) {
390 this->mYuvLayers++;
391 if (this->mHasDrmSurface == false) {
392 /* Assign MPP */
393 if (supportedExternalMPP != NULL)
394 supportedExternalMPP->mState = MPP_STATE_ASSIGNED;
395 if (supportedInternalMPP != NULL)
396 supportedInternalMPP->mState = MPP_STATE_ASSIGNED;
397
398 mForceOverlayLayerIndex = i;
399 layer.compositionType = HWC_OVERLAY;
400 mLayerInfos[i]->mExternalMPP = supportedExternalMPP;
401 mLayerInfos[i]->mInternalMPP = supportedInternalMPP;
402 mLayerInfos[i]->compositionType = layer.compositionType;
403
404 if ((mHwc->mS3DMode != S3D_MODE_DISABLED) &&
405 mHwc->mHdmiResolutionChanged)
406 mHwc->mS3DMode = S3D_MODE_RUNNING;
407 /* Set destination size as full screen */
408 if (mHwc->mS3DMode != S3D_MODE_DISABLED) {
409 layer.displayFrame.left = 0;
410 layer.displayFrame.top = 0;
411 layer.displayFrame.right = mXres;
412 layer.displayFrame.bottom = mYres;
413 }
414
415 if ((getDrmMode(handle->flags) != NO_DRM) &&
416 isBothMPPProcessingRequired(layer) &&
417 (supportedInternalMPP != NULL)) {
418 layer.displayFrame.right = layer.displayFrame.left +
419 ALIGN_DOWN(WIDTH(layer.displayFrame), supportedInternalMPP->getCropWidthAlign(layer));
420 layer.displayFrame.bottom = layer.displayFrame.top +
421 ALIGN_DOWN(HEIGHT(layer.displayFrame), supportedInternalMPP->getCropHeightAlign(layer));
422 layer.flags &= ~HWC_SKIP_RENDERING;
423 }
424
425 if ((getDrmMode(handle->flags) != NO_DRM) &&
426 (supportedInternalMPP != NULL)) {
427 if (WIDTH(layer.displayFrame) < supportedInternalMPP->getMinWidth(layer)) {
428 ALOGE("determineYuvOverlay layer %d displayFrame width %d is smaller than vpp minWidth %d",
429 i, WIDTH(layer.displayFrame), supportedInternalMPP->getMinWidth(layer));
430 layer.displayFrame.right = layer.displayFrame.left +
431 ALIGN_DOWN(WIDTH(layer.displayFrame), supportedInternalMPP->getMinWidth(layer));
432 }
433 if (HEIGHT(layer.displayFrame) < supportedInternalMPP->getMinHeight(layer)) {
434 ALOGE("determineYuvOverlay layer %d displayFrame height %d is smaller than vpp minHeight %d",
435 i, HEIGHT(layer.displayFrame), supportedInternalMPP->getMinHeight(layer));
436 layer.displayFrame.bottom = layer.displayFrame.top +
437 ALIGN_DOWN(HEIGHT(layer.displayFrame), supportedInternalMPP->getMinHeight(layer));
438 }
439 }
440 }
441 } else {
442 if (getDrmMode(handle->flags) != NO_DRM) {
443 /* This layer should be overlay but HWC can't handle it */
444 layer.compositionType = HWC_OVERLAY;
445 mLayerInfos[i]->compositionType = layer.compositionType;
446 layer.flags |= HWC_SKIP_RENDERING;
447 }
448 }
449
450 if (getDrmMode(handle->flags) != NO_DRM) {
451 this->mHasDrmSurface = true;
452 mForceOverlayLayerIndex = i;
453 }
454 }
455#endif
456 }
457 }
458}
459
460
461void ExynosExternalDisplay::determineSupportedOverlays(hwc_display_contents_1_t *contents)
462{
463#if defined(GSC_VIDEO)
464 if ((mHwc->mS3DMode != S3D_MODE_DISABLED) && (this->mYuvLayers == 1) && !mUseSubtitles) {
465 // UI layers will be skiped when S3D video is playing
466 for (size_t i = 0; i < contents->numHwLayers; i++) {
467 hwc_layer_1_t &layer = contents->hwLayers[i];
468 if (mForceOverlayLayerIndex != (int)i) {
469 layer.compositionType = HWC_OVERLAY;
470 layer.flags = HWC_SKIP_RENDERING;
471 }
472 }
473 }
474#endif
475
476#if !defined(GSC_VIDEO)
477 mForceFb = true;
478#endif
479
480 ExynosDisplay::determineSupportedOverlays(contents);
481 /*
482 * If GSC_VIDEO is not defined,
483 * all of layers are GLES except DRM video
484 */
485}
486
487void ExynosExternalDisplay::configureHandle(private_handle_t *handle, size_t index,
488 hwc_layer_1_t &layer, int fence_fd, decon_win_config &cfg)
489{
490 ExynosDisplay::configureHandle(handle, index, layer, fence_fd, cfg);
491 if ((mHwc->mS3DMode == S3D_MODE_RUNNING) &&
492 ((int)index == mForceOverlayLayerIndex) &&
493 (isPresetSupported(mHwc->mHdmiPreset) == false) &&
494 (mLayerInfos[index]->mInternalMPP != NULL) &&
495 (mLayerInfos[index]->mExternalMPP == NULL)) {
496 int S3DFormat = getS3DFormat(mHwc->mHdmiPreset);
497 if (S3DFormat == S3D_SBS)
498 cfg.src.w /= 2;
499 else if (S3DFormat == S3D_TB)
500 cfg.src.h /= 2;
501 }
502}
503
504int ExynosExternalDisplay::openHdmi()
505{
506 int ret = 0;
507 int sw_fd;
508
509 if (mHwc->externalDisplay->mDisplayFd > 0)
510 ret = mHwc->externalDisplay->mDisplayFd;
511 else {
512 mHwc->externalDisplay->mDisplayFd = open("/dev/graphics/fb1", O_RDWR);
513 if (mHwc->externalDisplay->mDisplayFd < 0) {
514 ALOGE("failed to open framebuffer for externalDisplay");
515 }
516 ret = mHwc->externalDisplay->mDisplayFd;
517 }
518
519 ALOGD("open fd for HDMI(%d)", ret);
520
521 return ret;
522}
523
524void ExynosExternalDisplay::closeHdmi()
525{
526 if (mDisplayFd > 0) {
527 close(mDisplayFd);
528 ALOGD("Close fd for HDMI");
529 }
530 mDisplayFd = -1;
531}
532
533void ExynosExternalDisplay::setHdmiStatus(bool status)
534{
535 if (status) {
536#if defined(USES_VIRTUAL_DISPLAY)
537 char value[PROPERTY_VALUE_MAX];
538 property_get("wlan.wfd.status", value, "disconnected");
539 bool bWFDDisconnected = !strcmp(value, "disconnected");
540
541 if (bWFDDisconnected) {
542#endif
543 if (mEnabled == false && mHwc->mS3DMode != S3D_MODE_DISABLED)
544 mHwc->mHdmiResolutionChanged = true;
545
546 if (mEnabled == false)
547 requestIONMemory();
548 enable();
549#if defined(USES_VIRTUAL_DISPLAY)
550 }
551#endif
552 } else {
553 disable();
554 closeHdmi();
555
556 if (mDRMTempBuffer != NULL) {
557 mAllocDevice->free(mAllocDevice, mDRMTempBuffer);
558 mDRMTempBuffer = NULL;
559 }
560 }
561}
562
563bool ExynosExternalDisplay::isPresetSupported(unsigned int preset)
564{
565 bool found = false;
566 int index = 0;
567 int ret = 0;
568 exynos_hdmi_data hdmi_data;
569 int dv_timings_index = getDVTimingsIndex(preset);
570
571 if (dv_timings_index < 0) {
572 ALOGE("%s: unsupported preset, %d", __func__, preset);
573 return -1;
574 }
575
576 hdmi_data.state = hdmi_data.EXYNOS_HDMI_STATE_ENUM_PRESET;
577 while (true) {
578 hdmi_data.etimings.index = index++;
579 ret = ioctl(this->mDisplayFd, EXYNOS_GET_HDMI_CONFIG, &hdmi_data);
580
581 if (ret < 0) {
582 if (errno == EINVAL)
583 break;
584 ALOGE("%s: enum_dv_timings error, %d", __func__, errno);
585 return -1;
586 }
587
588 ALOGV("%s: %d width=%d height=%d",
589 __func__, hdmi_data.etimings.index,
590 hdmi_data.etimings.timings.bt.width, hdmi_data.etimings.timings.bt.height);
591
592 if (is_same_dv_timings(&hdmi_data.etimings.timings, &dv_timings[dv_timings_index])) {
593 mXres = hdmi_data.etimings.timings.bt.width;
594 mYres = hdmi_data.etimings.timings.bt.height;
595 found = true;
596 mHwc->mHdmiCurrentPreset = preset;
597 break;
598 }
599 }
600 return found;
601}
602
603int ExynosExternalDisplay::getConfig()
604{
605 if (!mHwc->hdmi_hpd)
606 return -1;
607
608 exynos_hdmi_data hdmi_data;
609 int dv_timings_index = 0;
610
611 hdmi_data.state = hdmi_data.EXYNOS_HDMI_STATE_PRESET;
612 if (ioctl(this->mDisplayFd, EXYNOS_GET_HDMI_CONFIG, &hdmi_data) < 0) {
613 ALOGE("%s: g_dv_timings error, %d", __func__, errno);
614 return -1;
615 }
616
617 if (hwcHasApiVersion((hwc_composer_device_1_t*)mHwc, HWC_DEVICE_API_VERSION_1_4) == false)
618 mActiveConfigIndex = 0;
619 else {
620 /*
621 * getConfig is called only if cable is connected
622 * mActiveConfigIndex is 0 at this time
623 */
624 mActiveConfigIndex = 0;
625 }
626
627 for (int i = 0; i < SUPPORTED_DV_TIMINGS_NUM; i++) {
628 dv_timings_index = preset_index_mappings[i].dv_timings_index;
629 if (is_same_dv_timings(&hdmi_data.timings, &dv_timings[dv_timings_index])) {
630 float refreshRate = (float)((float)hdmi_data.timings.bt.pixelclock /
631 ((hdmi_data.timings.bt.width + hdmi_data.timings.bt.hfrontporch + hdmi_data.timings.bt.hsync + hdmi_data.timings.bt.hbackporch) *
632 (hdmi_data.timings.bt.height + hdmi_data.timings.bt.vfrontporch + hdmi_data.timings.bt.vsync + hdmi_data.timings.bt.vbackporch)));
633 mXres = hdmi_data.timings.bt.width;
634 mYres = hdmi_data.timings.bt.height;
635 mVsyncPeriod = 1000000000 / refreshRate;
636 mHwc->mHdmiCurrentPreset = preset_index_mappings[i].preset;
637 break;
638 }
639 }
640 ALOGD("HDMI resolution is (%d x %d)", mXres, mYres);
641
642 return 0;
643}
644
645int ExynosExternalDisplay::getDisplayConfigs(uint32_t *configs, size_t *numConfigs)
646{
647 int ret = 0;
648 if (!mHwc->hdmi_hpd)
649 return -1;
650
651 exynos_hdmi_data hdmi_data;
652 size_t index = 0;
653
654 cleanConfigurations();
655
656 /* configs store the index of mConfigurations */
657 hdmi_data.state = hdmi_data.EXYNOS_HDMI_STATE_ENUM_PRESET;
658 while (index < (*numConfigs)) {
659 hdmi_data.etimings.index = index;
660 ret = ioctl(this->mDisplayFd, EXYNOS_GET_HDMI_CONFIG, &hdmi_data);
661
662 if (ret < 0) {
663 if (errno == EINVAL) {
664 ALOGI("%s:: Total configurations %d", __func__, index);
665 break;
666 }
667 ALOGE("%s: enum_dv_timings error, %d", __func__, errno);
668 return -1;
669 }
670
671 for (size_t i = 0; i < SUPPORTED_DV_TIMINGS_NUM; i++) {
672 int dv_timings_index = preset_index_mappings[i].dv_timings_index;
673 if (is_same_dv_timings(&hdmi_data.etimings.timings, &dv_timings[dv_timings_index])) {
674 mConfigurations.push_back(dv_timings_index);
675 configs[mConfigurations.size() - 1] = dv_timings_index;
676 break;
677 }
678 }
679 index++;
680 }
681
682 ALOGD("HDMI resolution is (%d x %d)", mXres, mYres);
683 *numConfigs = mConfigurations.size();
684 dumpConfigurations();
685 return 0;
686}
687
688int ExynosExternalDisplay::getActiveConfig()
689{
690 if (!mHwc->hdmi_hpd)
691 return -1;
692
693 return mActiveConfigIndex;
694}
695
696void ExynosExternalDisplay::setHdmiResolution(int resolution, int s3dMode)
697{
698 if (resolution == 0)
699 resolution = mHwc->mHdmiCurrentPreset;
700 if (s3dMode == S3D_NONE) {
701 if (mHwc->mHdmiCurrentPreset == resolution)
702 return;
703 mHwc->mHdmiPreset = resolution;
704 mHwc->mHdmiResolutionChanged = true;
705 mHwc->procs->invalidate(mHwc->procs);
706 return;
707 }
708
709 switch (resolution) {
710 case HDMI_720P_60:
711 resolution = S3D_720P_60_BASE + s3dMode;
712 break;
713 case HDMI_720P_59_94:
714 resolution = S3D_720P_59_94_BASE + s3dMode;
715 break;
716 case HDMI_720P_50:
717 resolution = S3D_720P_50_BASE + s3dMode;
718 break;
719 case HDMI_1080P_24:
720 resolution = S3D_1080P_24_BASE + s3dMode;
721 break;
722 case HDMI_1080P_23_98:
723 resolution = S3D_1080P_23_98_BASE + s3dMode;
724 break;
725 case HDMI_1080P_30:
726 resolution = S3D_1080P_30_BASE + s3dMode;
727 break;
728 case HDMI_1080I_60:
729 if (s3dMode != S3D_SBS)
730 return;
731 resolution = V4L2_DV_1080I60_SB_HALF;
732 break;
733 case HDMI_1080I_59_94:
734 if (s3dMode != S3D_SBS)
735 return;
736 resolution = V4L2_DV_1080I59_94_SB_HALF;
737 break;
738 case HDMI_1080P_60:
739 if (s3dMode != S3D_SBS && s3dMode != S3D_TB)
740 return;
741 resolution = S3D_1080P_60_BASE + s3dMode;
742 break;
743 default:
744 return;
745 }
746 mHwc->mHdmiPreset = resolution;
747 mHwc->mHdmiResolutionChanged = true;
748 mHwc->mS3DMode = S3D_MODE_READY;
749 mHwc->procs->invalidate(mHwc->procs);
750}
751
752int ExynosExternalDisplay::setActiveConfig(int index)
753{
754 if (!mHwc->hdmi_hpd)
755 return -1;
756 /* Find Preset with index*/
757 int preset = -1;
758 unsigned int s3dMode = S3D_NONE;
759 preset = (int)preset_index_mappings[mConfigurations[index]].preset;
760
761 if (preset < 0) {
762 ALOGE("%s:: Unsupported preset, index(%d)", __func__, index);
763 return -1;
764 }
765
766 v4l2_dv_timings dv_timing = dv_timings[preset_index_mappings[mConfigurations[index]].dv_timings_index];
767 if (dv_timing.type == V4L2_DV_BT_SB_HALF)
768 s3dMode = S3D_SBS;
769 else if (dv_timing.type == V4L2_DV_BT_TB)
770 s3dMode = S3D_TB;
771 else
772 s3dMode = S3D_NONE;
773
774 setHdmiResolution(preset, s3dMode);
775 mActiveConfigIndex = index;
776 return 0;
777}
778
779int32_t ExynosExternalDisplay::getDisplayAttributes(const uint32_t attribute, uint32_t config)
780{
781 if (config >= SUPPORTED_DV_TIMINGS_NUM) {
782 ALOGE("%s:: Invalid config(%d), mConfigurations(%d)", __func__, config, mConfigurations.size());
783 return -EINVAL;
784 }
785
786 v4l2_dv_timings dv_timing = dv_timings[preset_index_mappings[config].dv_timings_index];
787 switch(attribute) {
788 case HWC_DISPLAY_VSYNC_PERIOD:
789 {
790 float refreshRate = (float)((float)dv_timing.bt.pixelclock /
791 ((dv_timing.bt.width + dv_timing.bt.hfrontporch + dv_timing.bt.hsync + dv_timing.bt.hbackporch) *
792 (dv_timing.bt.height + dv_timing.bt.vfrontporch + dv_timing.bt.vsync + dv_timing.bt.vbackporch)));
793 return (1000000000/refreshRate);
794 }
795 case HWC_DISPLAY_WIDTH:
796 return dv_timing.bt.width;
797
798 case HWC_DISPLAY_HEIGHT:
799 return dv_timing.bt.height;
800
801 case HWC_DISPLAY_DPI_X:
802 return this->mXdpi;
803
804 case HWC_DISPLAY_DPI_Y:
805 return this->mYdpi;
806
807 default:
808 ALOGE("unknown display attribute %u", attribute);
809 return -EINVAL;
810 }
811}
812
813void ExynosExternalDisplay::cleanConfigurations()
814{
815 mConfigurations.clear();
816}
817
818void ExynosExternalDisplay::dumpConfigurations()
819{
820 ALOGI("External display configurations:: total(%d), active configuration(%d)",
821 mConfigurations.size(), mActiveConfigIndex);
822 for (size_t i = 0; i < mConfigurations.size(); i++ ) {
823 unsigned int dv_timings_index = preset_index_mappings[mConfigurations[i]].dv_timings_index;
824 v4l2_dv_timings configuration = dv_timings[dv_timings_index];
825 float refresh_rate = (float)((float)configuration.bt.pixelclock /
826 ((configuration.bt.width + configuration.bt.hfrontporch + configuration.bt.hsync + configuration.bt.hbackporch) *
827 (configuration.bt.height + configuration.bt.vfrontporch + configuration.bt.vsync + configuration.bt.vbackporch)));
828 uint32_t vsyncPeriod = 1000000000 / refresh_rate;
829 ALOGI("%d : type(%d), %d x %d, fps(%f), vsyncPeriod(%d)", i, configuration.type, configuration.bt.width,
830 configuration.bt.height,
831 refresh_rate, vsyncPeriod);
832 }
833}
834
835int ExynosExternalDisplay::enable()
836{
837 if (mEnabled)
838 return 0;
839
840 if (mBlanked)
841 return 0;
842
843 char value[PROPERTY_VALUE_MAX];
844 property_get("persist.hdmi.hdcp_enabled", value, "1");
845 int hdcp_enabled = atoi(value);
846 ALOGD("%s:: hdcp_enabled (%d)", __func__, hdcp_enabled);
847
848 exynos_hdmi_data hdmi_data;
849 hdmi_data.state = hdmi_data.EXYNOS_HDMI_STATE_HDCP;
850 hdmi_data.hdcp = hdcp_enabled;
851
852 if ((mDisplayFd < 0) && (openHdmi() < 0))
853 return -1;
854
855 if (ioctl(this->mDisplayFd, EXYNOS_SET_HDMI_CONFIG, &hdmi_data) < 0) {
856 ALOGE("%s: failed to set HDCP status %d", __func__, errno);
857 }
858
859 /* "2" is RGB601_16_235 */
860 property_get("persist.hdmi.color_range", value, "2");
861 int color_range = atoi(value);
862
863#if 0 // This should be changed
864 if (exynos_v4l2_s_ctrl(mMixerLayers[mUiIndex].fd, V4L2_CID_TV_SET_COLOR_RANGE,
865 color_range) < 0)
866 ALOGE("%s: s_ctrl(CID_TV_COLOR_RANGE) failed %d", __func__, errno);
867#endif
868
869 int err = ioctl(mDisplayFd, FBIOBLANK, FB_BLANK_UNBLANK);
870 if (err < 0) {
871 if (errno == EBUSY)
872 ALOGI("unblank ioctl failed (display already unblanked)");
873 else
874 ALOGE("unblank ioctl failed: %s", strerror(errno));
875 return -errno;
876 }
877
878 mEnabled = true;
879 return 0;
880}
881
882void ExynosExternalDisplay::disable()
883{
884 if (!mEnabled)
885 return;
886
887 blank();
888
889 mEnabled = false;
890 checkIONBufferPrepared();
891}
892
893void ExynosExternalDisplay::setPreset(int preset)
894{
895 mHwc->mHdmiResolutionChanged = false;
896 mHwc->mHdmiResolutionHandled = false;
897 mHwc->hdmi_hpd = false;
898 int dv_timings_index = getDVTimingsIndex(preset);
899 if (dv_timings_index < 0) {
900 ALOGE("invalid preset(%d)", preset);
901 return;
902 }
903
904 disable();
905
906 exynos_hdmi_data hdmi_data;
907 hdmi_data.state = hdmi_data.EXYNOS_HDMI_STATE_PRESET;
908 hdmi_data.timings = dv_timings[dv_timings_index];
909 if (ioctl(this->mDisplayFd, EXYNOS_SET_HDMI_CONFIG, &hdmi_data) != -1) {
910 if (mHwc->procs)
911 mHwc->procs->hotplug(mHwc->procs, HWC_DISPLAY_EXTERNAL, false);
912 }
913}
914
915int ExynosExternalDisplay::convert3DTo2D(int preset)
916{
917 switch (preset) {
918 case V4L2_DV_720P60_FP:
919 case V4L2_DV_720P60_SB_HALF:
920 case V4L2_DV_720P60_TB:
921 return V4L2_DV_720P60;
922 case V4L2_DV_720P50_FP:
923 case V4L2_DV_720P50_SB_HALF:
924 case V4L2_DV_720P50_TB:
925 return V4L2_DV_720P50;
926 case V4L2_DV_1080P60_SB_HALF:
927 case V4L2_DV_1080P60_TB:
928 return V4L2_DV_1080P60;
929 case V4L2_DV_1080P30_FP:
930 case V4L2_DV_1080P30_SB_HALF:
931 case V4L2_DV_1080P30_TB:
932 return V4L2_DV_1080P30;
933 default:
934 return HDMI_PRESET_ERROR;
935 }
936}
937
938void ExynosExternalDisplay::setHdcpStatus(int status)
939{
940 exynos_hdmi_data hdmi_data;
941 hdmi_data.state = hdmi_data.EXYNOS_HDMI_STATE_HDCP;
942 hdmi_data.hdcp = !!status;
943 if (ioctl(this->mDisplayFd, EXYNOS_SET_HDMI_CONFIG, &hdmi_data) < 0) {
944 ALOGE("%s: failed to set HDCP status %d", __func__, errno);
945 }
946}
947
948void ExynosExternalDisplay::setAudioChannel(uint32_t channels)
949{
950 exynos_hdmi_data hdmi_data;
951 hdmi_data.state = hdmi_data.EXYNOS_HDMI_STATE_AUDIO;
952 hdmi_data.audio_info = channels;
953 if (ioctl(this->mDisplayFd, EXYNOS_SET_HDMI_CONFIG, &hdmi_data) < 0) {
954 ALOGE("%s: failed to set audio channels %d", __func__, errno);
955 }
956}
957
958uint32_t ExynosExternalDisplay::getAudioChannel()
959{
960 int channels = 0;
961
962 exynos_hdmi_data hdmi_data;
963 hdmi_data.state = hdmi_data.EXYNOS_HDMI_STATE_AUDIO;
964 if (ioctl(this->mDisplayFd, EXYNOS_GET_HDMI_CONFIG, &hdmi_data) < 0) {
965 ALOGE("%s: failed to get audio channels %d", __func__, errno);
966 }
967 channels = hdmi_data.audio_info;
968
969 return channels;
970}
971
972int ExynosExternalDisplay::getCecPaddr()
973{
974 if (!mHwc->hdmi_hpd)
975 return -1;
976
977 exynos_hdmi_data hdmi_data;
978
979 hdmi_data.state = hdmi_data.EXYNOS_HDMI_STATE_CEC_ADDR;
980 if (ioctl(this->mDisplayFd, EXYNOS_GET_HDMI_CONFIG, &hdmi_data) < 0) {
981 ALOGE("%s: g_dv_timings error, %d", __func__, errno);
982 return -1;
983 }
984
985 return (int)hdmi_data.cec_addr;
986}
987
988int ExynosExternalDisplay::blank()
989{
990 int fence = clearDisplay();
991 if (fence >= 0)
992 close(fence);
993 int err = ioctl(mDisplayFd, FBIOBLANK, FB_BLANK_POWERDOWN);
994 if (err < 0) {
995 if (errno == EBUSY)
996 ALOGI("blank ioctl failed (display already blanked)");
997 else
998 ALOGE("blank ioctl failed: %s", strerror(errno));
999 return -errno;
1000 }
1001
1002 return 0;
1003}
1004
1005int ExynosExternalDisplay::clearDisplay()
1006{
1007 if (!mEnabled)
1008 return 0;
1009 return ExynosDisplay::clearDisplay();
1010}
1011
1012void ExynosExternalDisplay::requestIONMemory()
1013{
1014 if (mReserveMemFd > 0) {
1015 unsigned int value;
1016 char buffer[4096];
1017 memset(buffer, 0, sizeof(buffer));
1018 int err = lseek(mReserveMemFd, 0, SEEK_SET);
1019 err = read(mReserveMemFd, buffer, sizeof(buffer));
1020 value = atoi(buffer);
1021
1022 if ((err > 0) && (value == 0)) {
1023 memset(buffer, 0, sizeof(buffer));
1024 buffer[0] = '2';
1025 if (write(mReserveMemFd, buffer, sizeof(buffer)) < 0)
1026 ALOGE("fail to request isolation of memmory for HDMI");
1027 else
1028 ALOGV("isolation of memmory for HDMI was requested");
1029 } else {
1030 if (err < 0)
1031 ALOGE("fail to read hdmi_reserve_mem_fd");
1032 else
1033 ALOGE("ion memmory for HDMI is isolated already");
1034 }
1035 }
1036}
1037void ExynosExternalDisplay::freeIONMemory()
1038{
1039 if ((mHwc->hdmi_hpd == false) && (mReserveMemFd > 0)) {
1040 unsigned int value;
1041 char buffer[4096];
1042 int ret = 0;
1043 memset(buffer, 0, sizeof(buffer));
1044 int err = lseek(mReserveMemFd, 0, SEEK_SET);
1045 err = read(mReserveMemFd, buffer, sizeof(buffer));
1046 value = atoi(buffer);
1047 if ((err > 0) && (value == 1)) {
1048 memset(buffer, 0, sizeof(buffer));
1049 buffer[0] = '0';
1050 if (write(mReserveMemFd, buffer, sizeof(buffer)) < 0)
1051 ALOGE("fail to request isolation of memmory for HDMI");
1052 else
1053 ALOGV("deisolation of memmory for HDMI was requested");
1054 } else {
1055 if (err < 0)
1056 ALOGE("fail to read hdmi_reserve_mem_fd");
1057 else
1058 ALOGE("ion memmory for HDMI is deisolated already");
1059 }
1060 mFlagIONBufferAllocated = false;
1061 }
1062}
1063bool ExynosExternalDisplay::checkIONBufferPrepared()
1064{
1065 if (mFlagIONBufferAllocated)
1066 return true;
1067
1068 if ((mReserveMemFd > 0)) {
1069 unsigned int value;
1070 char buffer[4096];
1071 int ret = 0;
1072 memset(buffer, 0, sizeof(buffer));
1073 int err = lseek(mReserveMemFd, 0, SEEK_SET);
1074 err = read(mReserveMemFd, buffer, sizeof(buffer));
1075 value = atoi(buffer);
1076
1077 if ((err > 0) && (value == 1)) {
1078 mFlagIONBufferAllocated = true;
1079 return true;
1080 } else {
1081 mFlagIONBufferAllocated = false;
1082 return false;
1083 }
1084 return false;
1085 } else {
1086 /* isolation of video_ext is not used */
1087 mFlagIONBufferAllocated = true;
1088 return true;
1089 }
1090}
1091
1092int ExynosExternalDisplay::configureDRMSkipHandle(decon_win_config &cfg)
1093{
1094 int err = 0;
1095 private_handle_t *dst_handle = NULL;
1096
1097 if (mDRMTempBuffer == NULL) {
1098 int dst_stride;
1099 int usage = GRALLOC_USAGE_SW_READ_NEVER |
1100 GRALLOC_USAGE_SW_WRITE_NEVER |
1101 GRALLOC_USAGE_HW_COMPOSER;
1102
1103 err = mAllocDevice->alloc(mAllocDevice, 32, 32, HAL_PIXEL_FORMAT_BGRA_8888,
1104 usage, &mDRMTempBuffer, &dst_stride);
1105 if (err < 0) {
1106 ALOGE("failed to allocate destination buffer(%dx%d): %s", 32, 32,
1107 strerror(-err));
1108 return err;
1109 } else {
1110 ALOGV("temBuffer for DRM video was allocated");
1111 }
1112 }
1113
1114 dst_handle = private_handle_t::dynamicCast(mDRMTempBuffer);
1115 cfg.state = cfg.DECON_WIN_STATE_BUFFER;
1116 cfg.fd_idma[0] = dst_handle->fd;
1117 cfg.fd_idma[1] = dst_handle->fd1;
1118 cfg.fd_idma[2] = dst_handle->fd2;
1119 cfg.dst.f_w = dst_handle->stride;
1120 cfg.dst.f_h = dst_handle->vstride;
1121 cfg.dst.x = 0;
1122 cfg.dst.y = 0;
1123 cfg.dst.w = cfg.dst.f_w;
1124 cfg.dst.h = cfg.dst.f_h;
1125 cfg.format = halFormatToS3CFormat(HAL_PIXEL_FORMAT_RGBX_8888);
1126
1127 cfg.src.f_w = dst_handle->stride;
1128 cfg.src.f_h = dst_handle->vstride;
1129 cfg.src.x = 0;
1130 cfg.src.y = 0;
1131 cfg.src.w = cfg.dst.f_w;
1132 cfg.src.h = cfg.dst.f_h;
1133 cfg.blending = DECON_BLENDING_NONE;
1134 cfg.fence_fd = -1;
1135 cfg.plane_alpha = 255;
1136
1137 return 0;
1138}
1139
1140void ExynosExternalDisplay::freeExtVideoBuffers()
1141{
1142 if (mFlagIONBufferAllocated)
1143 freeIONMemory();
1144}
1145
1146void ExynosExternalDisplay::doPreProcessing(hwc_display_contents_1_t* contents)
1147{
1148 mInternalDMAs.clear();
1149 mInternalDMAs.add(IDMA_G3);
1150 ExynosDisplay::doPreProcessing(contents);
1151}