3 #include "ExynosHWCUtils.h"
4 #include "ExynosMPPModule.h"
5 #include "ExynosExternalDisplay.h"
6 #include "ExynosSecondaryDisplayModule.h"
10 extern struct v4l2_dv_timings dv_timings
[];
11 bool is_same_dv_timings(const struct v4l2_dv_timings
*t1
,
12 const struct v4l2_dv_timings
*t2
)
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
)))
32 int ExynosExternalDisplay::getDVTimingsIndex(int preset
)
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
;
41 ExynosExternalDisplay::ExynosExternalDisplay(struct exynos5_hwc_composer_device_1_t
*pdev
)
42 : ExynosDisplay(EXYNOS_EXTERNAL_DISPLAY
, pdev
),
48 mFlagIONBufferAllocated(false)
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
);
60 ALOGI("Open %s", HDMI_RESERVE_MEM_DEV_NAME
);
63 ExynosExternalDisplay::~ExynosExternalDisplay()
65 if (mDRMTempBuffer
!= NULL
) {
66 mAllocDevice
->free(mAllocDevice
, mDRMTempBuffer
);
67 mDRMTempBuffer
= NULL
;
69 if (mReserveMemFd
> 0)
73 void ExynosExternalDisplay::allocateLayerInfos(hwc_display_contents_1_t
* contents
)
75 ExynosDisplay::allocateLayerInfos(contents
);
78 int ExynosExternalDisplay::prepare(hwc_display_contents_1_t
* contents
)
80 ExynosDisplay::prepare(contents
);
84 int ExynosExternalDisplay::postMPPM2M(hwc_layer_1_t
&layer
, struct decon_win_config
*config
, int win_map
, int index
)
87 private_handle_t
*handle
= private_handle_t::dynamicCast(layer
.handle
);
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;
101 handle
->flags
|= GRALLOC_USAGE_VIDEO_EXT
;
105 return ExynosDisplay::postMPPM2M(layer
, config
, win_map
, index
);
108 void ExynosExternalDisplay::handleStaticLayers(hwc_display_contents_1_t
*contents
, struct decon_win_config_data
&win_data
, int __unused tot_ovly_wins
)
111 if (mLastFbWindow
>= NUM_HW_WINDOWS
- 1) {
112 ALOGE("handleStaticLayers:: invalid mLastFbWindow(%d)", mLastFbWindow
);
115 win_map
= mLastFbWindow
+ 1;
116 ALOGV("[USE] SKIP_STATIC_LAYER_COMP, mLastFbWindow(%d), win_map(%d)\n", mLastFbWindow
, win_map
);
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;
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;
134 int ExynosExternalDisplay::postFrame(hwc_display_contents_1_t
* contents
)
136 struct decon_win_config_data win_data
;
137 struct decon_win_config
*config
= win_data
.config
;
139 int tot_ovly_wins
= 0;
140 bool hdmiDisabled
= false;
142 memset(mLastHandles
, 0, sizeof(mLastHandles
));
143 memset(mLastMPPMap
, 0, sizeof(mLastMPPMap
));
144 memset(config
, 0, sizeof(win_data
.config
));
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;
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;
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;
169 if ((layer
.compositionType
== HWC_OVERLAY
) ||
170 (mFbNeeded
== true && layer
.compositionType
== HWC_FRAMEBUFFER_TARGET
)) {
171 mLastHandles
[window_index
] = layer
.handle
;
173 if (handle
== NULL
) {
174 if (layer
.acquireFenceFd
>= 0)
175 close(layer
.acquireFenceFd
);
176 layer
.acquireFenceFd
= -1;
177 layer
.releaseFenceFd
= -1;
181 if (getDrmMode(handle
->flags
) == SECURE_DRM
)
182 config
[window_index
].protection
= 1;
184 config
[window_index
].protection
= 0;
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
);
192 * HDMI was disabled by setPreset
193 * This frame will be handled from next frame
195 if (layer
.acquireFenceFd
>= 0)
196 close(layer
.acquireFenceFd
);
197 layer
.acquireFenceFd
= -1;
198 layer
.releaseFenceFd
= -1;
199 layer
.flags
= HWC_SKIP_RENDERING
;
203 mHwc
->mS3DMode
= S3D_MODE_RUNNING
;
204 mHwc
->mHdmiResolutionChanged
= false;
205 mHwc
->mHdmiResolutionHandled
= true;
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
;
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
;
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
;
226 if (postMPPM2M(layer
, config
, window_index
, i
) < 0)
229 configureOverlay(&layer
, i
, config
[window_index
]);
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
;
238 for (size_t i
= 0; i
< NUM_HW_WINDOWS
; i
++) {
239 ALOGV("external display: window %u configuration:", i
);
240 dumpConfig(config
[i
]);
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;
254 if (this->mVirtualOverlayFlag
) {
255 handleStaticLayers(contents
, win_data
, tot_ovly_wins
);
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;
266 if (checkConfigChanged(win_data
, mLastConfigData
) == false)
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
;
272 if ((layer
.compositionType
== HWC_OVERLAY
) ||
273 (layer
.compositionType
== HWC_FRAMEBUFFER_TARGET
)) {
274 if (layer
.acquireFenceFd
>= 0)
275 close(layer
.acquireFenceFd
);
277 if (mLayerInfos
[i
]->mExternalMPP
!= NULL
) {
278 mLayerInfos
[i
]->mExternalMPP
->mCurrentBuf
= (mLayerInfos
[i
]->mExternalMPP
->mCurrentBuf
+ 1) % mLayerInfos
[i
]->mExternalMPP
->mNumAvailableDstBuffers
;
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
);
290 ALOGE("ioctl S3CFB_WIN_CONFIG failed: %s", strerror(errno
));
294 memcpy(&(this->mLastConfigData
), &win_data
, sizeof(win_data
));
296 if (!this->mVirtualOverlayFlag
)
297 this->mLastFbWindow
= mFbWindow
;
299 if ((mYuvLayers
!= 0) && (mDRMTempBuffer
!= NULL
)) {
300 mAllocDevice
->free(mAllocDevice
, mDRMTempBuffer
);
301 mDRMTempBuffer
= NULL
;
303 return win_data
.fence
;
306 int ExynosExternalDisplay::set(hwc_display_contents_1_t
* contents
)
309 bool drm_skipped
= false;
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;
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
;
329 layer
.flags
&= ~(HWC_SKIP_RENDERING
);
332 err
= ExynosDisplay::set(contents
);
334 /* HDMI was disabled to change S3D mode */
335 if (mEnabled
== false)
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
);
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
);
353 mHwc
->mS3DMode
= S3D_MODE_STOPPING
;
354 mHwc
->mHdmiPreset
= preset
;
356 mHwc
->procs
->invalidate(mHwc
->procs
);
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
;
368 void ExynosExternalDisplay::determineYuvOverlay(hwc_display_contents_1_t
*contents
)
370 mForceOverlayLayerIndex
= -1;
371 mHasDrmSurface
= false;
373 bool useVPPOverlayFlag
= false;
375 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
376 ExynosMPPModule
* supportedInternalMPP
= NULL
;
377 ExynosMPPModule
* supportedExternalMPP
= NULL
;
379 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
380 useVPPOverlayFlag
= false;
382 private_handle_t
*handle
= private_handle_t::dynamicCast(layer
.handle
);
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
)) {
391 if (this->mHasDrmSurface
== false) {
393 if (supportedExternalMPP
!= NULL
)
394 supportedExternalMPP
->mState
= MPP_STATE_ASSIGNED
;
395 if (supportedInternalMPP
!= NULL
)
396 supportedInternalMPP
->mState
= MPP_STATE_ASSIGNED
;
398 mForceOverlayLayerIndex
= i
;
399 layer
.compositionType
= HWC_OVERLAY
;
400 mLayerInfos
[i
]->mExternalMPP
= supportedExternalMPP
;
401 mLayerInfos
[i
]->mInternalMPP
= supportedInternalMPP
;
402 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
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
;
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
;
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
));
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
));
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
;
450 if (getDrmMode(handle
->flags
) != NO_DRM
) {
451 this->mHasDrmSurface
= true;
452 mForceOverlayLayerIndex
= i
;
461 void ExynosExternalDisplay::determineSupportedOverlays(hwc_display_contents_1_t
*contents
)
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
;
476 #if !defined(GSC_VIDEO)
480 ExynosDisplay::determineSupportedOverlays(contents
);
482 * If GSC_VIDEO is not defined,
483 * all of layers are GLES except DRM video
487 void ExynosExternalDisplay::configureHandle(private_handle_t
*handle
, size_t index
,
488 hwc_layer_1_t
&layer
, int fence_fd
, decon_win_config
&cfg
)
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
)
499 else if (S3DFormat
== S3D_TB
)
504 int ExynosExternalDisplay::openHdmi()
509 if (mHwc
->externalDisplay
->mDisplayFd
> 0)
510 ret
= mHwc
->externalDisplay
->mDisplayFd
;
512 mHwc
->externalDisplay
->mDisplayFd
= open("/dev/graphics/fb1", O_RDWR
);
513 if (mHwc
->externalDisplay
->mDisplayFd
< 0) {
514 ALOGE("failed to open framebuffer for externalDisplay");
516 ret
= mHwc
->externalDisplay
->mDisplayFd
;
519 ALOGD("open fd for HDMI(%d)", ret
);
524 void ExynosExternalDisplay::closeHdmi()
526 if (mDisplayFd
> 0) {
528 ALOGD("Close fd for HDMI");
533 void ExynosExternalDisplay::setHdmiStatus(bool 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");
541 if (bWFDDisconnected
) {
543 if (mEnabled
== false && mHwc
->mS3DMode
!= S3D_MODE_DISABLED
)
544 mHwc
->mHdmiResolutionChanged
= true;
546 if (mEnabled
== false)
549 #if defined(USES_VIRTUAL_DISPLAY)
556 if (mDRMTempBuffer
!= NULL
) {
557 mAllocDevice
->free(mAllocDevice
, mDRMTempBuffer
);
558 mDRMTempBuffer
= NULL
;
563 bool ExynosExternalDisplay::isPresetSupported(unsigned int preset
)
568 exynos_hdmi_data hdmi_data
;
569 int dv_timings_index
= getDVTimingsIndex(preset
);
571 if (dv_timings_index
< 0) {
572 ALOGE("%s: unsupported preset, %d", __func__
, preset
);
576 hdmi_data
.state
= hdmi_data
.EXYNOS_HDMI_STATE_ENUM_PRESET
;
578 hdmi_data
.etimings
.index
= index
++;
579 ret
= ioctl(this->mDisplayFd
, EXYNOS_GET_HDMI_CONFIG
, &hdmi_data
);
584 ALOGE("%s: enum_dv_timings error, %d", __func__
, errno
);
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
);
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
;
596 mHwc
->mHdmiCurrentPreset
= preset
;
603 int ExynosExternalDisplay::getConfig()
608 exynos_hdmi_data hdmi_data
;
609 int dv_timings_index
= 0;
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
);
617 if (hwcHasApiVersion((hwc_composer_device_1_t
*)mHwc
, HWC_DEVICE_API_VERSION_1_4
) == false)
618 mActiveConfigIndex
= 0;
621 * getConfig is called only if cable is connected
622 * mActiveConfigIndex is 0 at this time
624 mActiveConfigIndex
= 0;
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
;
640 ALOGD("HDMI resolution is (%d x %d)", mXres
, mYres
);
645 int ExynosExternalDisplay::getDisplayConfigs(uint32_t *configs
, size_t *numConfigs
)
651 exynos_hdmi_data hdmi_data
;
654 cleanConfigurations();
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
);
663 if (errno
== EINVAL
) {
664 ALOGI("%s:: Total configurations %d", __func__
, index
);
667 ALOGE("%s: enum_dv_timings error, %d", __func__
, errno
);
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
;
682 ALOGD("HDMI resolution is (%d x %d)", mXres
, mYres
);
683 *numConfigs
= mConfigurations
.size();
684 dumpConfigurations();
688 int ExynosExternalDisplay::getActiveConfig()
693 return mActiveConfigIndex
;
696 void ExynosExternalDisplay::setHdmiResolution(int resolution
, int s3dMode
)
699 resolution
= mHwc
->mHdmiCurrentPreset
;
700 if (s3dMode
== S3D_NONE
) {
701 if (mHwc
->mHdmiCurrentPreset
== resolution
)
703 mHwc
->mHdmiPreset
= resolution
;
704 mHwc
->mHdmiResolutionChanged
= true;
705 mHwc
->procs
->invalidate(mHwc
->procs
);
709 switch (resolution
) {
711 resolution
= S3D_720P_60_BASE
+ s3dMode
;
713 case HDMI_720P_59_94
:
714 resolution
= S3D_720P_59_94_BASE
+ s3dMode
;
717 resolution
= S3D_720P_50_BASE
+ s3dMode
;
720 resolution
= S3D_1080P_24_BASE
+ s3dMode
;
722 case HDMI_1080P_23_98
:
723 resolution
= S3D_1080P_23_98_BASE
+ s3dMode
;
726 resolution
= S3D_1080P_30_BASE
+ s3dMode
;
729 if (s3dMode
!= S3D_SBS
)
731 resolution
= V4L2_DV_1080I60_SB_HALF
;
733 case HDMI_1080I_59_94
:
734 if (s3dMode
!= S3D_SBS
)
736 resolution
= V4L2_DV_1080I59_94_SB_HALF
;
739 if (s3dMode
!= S3D_SBS
&& s3dMode
!= S3D_TB
)
741 resolution
= S3D_1080P_60_BASE
+ s3dMode
;
746 mHwc
->mHdmiPreset
= resolution
;
747 mHwc
->mHdmiResolutionChanged
= true;
748 mHwc
->mS3DMode
= S3D_MODE_READY
;
749 mHwc
->procs
->invalidate(mHwc
->procs
);
752 int ExynosExternalDisplay::setActiveConfig(int index
)
756 /* Find Preset with index*/
758 unsigned int s3dMode
= S3D_NONE
;
759 preset
= (int)preset_index_mappings
[mConfigurations
[index
]].preset
;
762 ALOGE("%s:: Unsupported preset, index(%d)", __func__
, index
);
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
)
769 else if (dv_timing
.type
== V4L2_DV_BT_TB
)
774 setHdmiResolution(preset
, s3dMode
);
775 mActiveConfigIndex
= index
;
779 int32_t ExynosExternalDisplay::getDisplayAttributes(const uint32_t attribute
, uint32_t config
)
781 if (config
>= SUPPORTED_DV_TIMINGS_NUM
) {
782 ALOGE("%s:: Invalid config(%d), mConfigurations(%d)", __func__
, config
, mConfigurations
.size());
786 v4l2_dv_timings dv_timing
= dv_timings
[preset_index_mappings
[config
].dv_timings_index
];
788 case HWC_DISPLAY_VSYNC_PERIOD
:
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
);
795 case HWC_DISPLAY_WIDTH
:
796 return dv_timing
.bt
.width
;
798 case HWC_DISPLAY_HEIGHT
:
799 return dv_timing
.bt
.height
;
801 case HWC_DISPLAY_DPI_X
:
804 case HWC_DISPLAY_DPI_Y
:
808 ALOGE("unknown display attribute %u", attribute
);
813 void ExynosExternalDisplay::cleanConfigurations()
815 mConfigurations
.clear();
818 void ExynosExternalDisplay::dumpConfigurations()
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
);
835 int ExynosExternalDisplay::enable()
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
);
848 exynos_hdmi_data hdmi_data
;
849 hdmi_data
.state
= hdmi_data
.EXYNOS_HDMI_STATE_HDCP
;
850 hdmi_data
.hdcp
= hdcp_enabled
;
852 if ((mDisplayFd
< 0) && (openHdmi() < 0))
855 if (ioctl(this->mDisplayFd
, EXYNOS_SET_HDMI_CONFIG
, &hdmi_data
) < 0) {
856 ALOGE("%s: failed to set HDCP status %d", __func__
, errno
);
859 /* "2" is RGB601_16_235 */
860 property_get("persist.hdmi.color_range", value
, "2");
861 int color_range
= atoi(value
);
863 #if 0 // This should be changed
864 if (exynos_v4l2_s_ctrl(mMixerLayers
[mUiIndex
].fd
, V4L2_CID_TV_SET_COLOR_RANGE
,
866 ALOGE("%s: s_ctrl(CID_TV_COLOR_RANGE) failed %d", __func__
, errno
);
869 int err
= ioctl(mDisplayFd
, FBIOBLANK
, FB_BLANK_UNBLANK
);
872 ALOGI("unblank ioctl failed (display already unblanked)");
874 ALOGE("unblank ioctl failed: %s", strerror(errno
));
882 void ExynosExternalDisplay::disable()
890 checkIONBufferPrepared();
893 void ExynosExternalDisplay::setPreset(int preset
)
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
);
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) {
911 mHwc
->procs
->hotplug(mHwc
->procs
, HWC_DISPLAY_EXTERNAL
, false);
915 int ExynosExternalDisplay::convert3DTo2D(int 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
;
934 return HDMI_PRESET_ERROR
;
938 void ExynosExternalDisplay::setHdcpStatus(int status
)
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
);
948 void ExynosExternalDisplay::setAudioChannel(uint32_t channels
)
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
);
958 uint32_t ExynosExternalDisplay::getAudioChannel()
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
);
967 channels
= hdmi_data
.audio_info
;
972 int ExynosExternalDisplay::getCecPaddr()
977 exynos_hdmi_data hdmi_data
;
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
);
985 return (int)hdmi_data
.cec_addr
;
988 int ExynosExternalDisplay::blank()
990 int fence
= clearDisplay();
993 int err
= ioctl(mDisplayFd
, FBIOBLANK
, FB_BLANK_POWERDOWN
);
996 ALOGI("blank ioctl failed (display already blanked)");
998 ALOGE("blank ioctl failed: %s", strerror(errno
));
1005 int ExynosExternalDisplay::clearDisplay()
1009 return ExynosDisplay::clearDisplay();
1012 void ExynosExternalDisplay::requestIONMemory()
1014 if (mReserveMemFd
> 0) {
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
);
1022 if ((err
> 0) && (value
== 0)) {
1023 memset(buffer
, 0, sizeof(buffer
));
1025 if (write(mReserveMemFd
, buffer
, sizeof(buffer
)) < 0)
1026 ALOGE("fail to request isolation of memmory for HDMI");
1028 ALOGV("isolation of memmory for HDMI was requested");
1031 ALOGE("fail to read hdmi_reserve_mem_fd");
1033 ALOGE("ion memmory for HDMI is isolated already");
1037 void ExynosExternalDisplay::freeIONMemory()
1039 if ((mHwc
->hdmi_hpd
== false) && (mReserveMemFd
> 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
));
1050 if (write(mReserveMemFd
, buffer
, sizeof(buffer
)) < 0)
1051 ALOGE("fail to request isolation of memmory for HDMI");
1053 ALOGV("deisolation of memmory for HDMI was requested");
1056 ALOGE("fail to read hdmi_reserve_mem_fd");
1058 ALOGE("ion memmory for HDMI is deisolated already");
1060 mFlagIONBufferAllocated
= false;
1063 bool ExynosExternalDisplay::checkIONBufferPrepared()
1065 if (mFlagIONBufferAllocated
)
1068 if ((mReserveMemFd
> 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
);
1077 if ((err
> 0) && (value
== 1)) {
1078 mFlagIONBufferAllocated
= true;
1081 mFlagIONBufferAllocated
= false;
1086 /* isolation of video_ext is not used */
1087 mFlagIONBufferAllocated
= true;
1092 int ExynosExternalDisplay::configureDRMSkipHandle(decon_win_config
&cfg
)
1095 private_handle_t
*dst_handle
= NULL
;
1097 if (mDRMTempBuffer
== NULL
) {
1099 int usage
= GRALLOC_USAGE_SW_READ_NEVER
|
1100 GRALLOC_USAGE_SW_WRITE_NEVER
|
1101 GRALLOC_USAGE_HW_COMPOSER
;
1103 err
= mAllocDevice
->alloc(mAllocDevice
, 32, 32, HAL_PIXEL_FORMAT_BGRA_8888
,
1104 usage
, &mDRMTempBuffer
, &dst_stride
);
1106 ALOGE("failed to allocate destination buffer(%dx%d): %s", 32, 32,
1110 ALOGV("temBuffer for DRM video was allocated");
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
;
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
);
1127 cfg
.src
.f_w
= dst_handle
->stride
;
1128 cfg
.src
.f_h
= dst_handle
->vstride
;
1131 cfg
.src
.w
= cfg
.dst
.f_w
;
1132 cfg
.src
.h
= cfg
.dst
.f_h
;
1133 cfg
.blending
= DECON_BLENDING_NONE
;
1135 cfg
.plane_alpha
= 255;
1140 void ExynosExternalDisplay::freeExtVideoBuffers()
1142 if (mFlagIONBufferAllocated
)
1146 void ExynosExternalDisplay::doPreProcessing(hwc_display_contents_1_t
* contents
)
1148 mInternalDMAs
.clear();
1149 mInternalDMAs
.add(IDMA_G3
);
1150 ExynosDisplay::doPreProcessing(contents
);