libhwcutils: resolve compilation errors
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos.git] / libhdmi_legacy / ExynosExternalDisplay.cpp
CommitLineData
5763fb39
T
1#include "ExynosHWC.h"
2#include "ExynosHWCUtils.h"
3#include "ExynosMPPModule.h"
4#include "ExynosOverlayDisplay.h"
5#include "ExynosExternalDisplay.h"
6#include <errno.h>
7
8#if defined(USE_DV_TIMINGS)
9extern struct v4l2_dv_timings dv_timings[];
10
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#endif
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
41inline bool hdmi_src_cfg_changed(exynos_mpp_img &c1, exynos_mpp_img &c2)
42{
43 return c1.format != c2.format ||
44 c1.rot != c2.rot ||
45 c1.cacheable != c2.cacheable ||
46 c1.drmMode != c2.drmMode ||
47 c1.fw != c2.fw ||
48 c1.fh != c2.fh;
49}
50
51ExynosExternalDisplay::ExynosExternalDisplay(struct exynos5_hwc_composer_device_1_t *pdev)
52 : ExynosDisplay(1),
53 mMixer(-1),
54 mEnabled(false),
55 mBlanked(false),
56 mIsFbLayer(false),
57 mIsVideoLayer(false),
58 mFbStarted(false),
59 mVideoStarted(false),
60 mHasFbComposition(false),
61 mHasSkipLayer(false),
62 mUiIndex(0),
63 mVideoIndex(1),
64 mVirtualOverlayFlag(0)
65{
66 mIsCameraStarted = false;
67 mFBT_Transform = 0;
68 mUseProtectedLayer = false;
69#if defined(USE_GRALLOC_FLAG_FOR_HDMI)
70 mUseScreenshootLayer = false;
71 mLocalExternalDisplayPause = false;
72#endif
73 mNumMPPs = 1;
74 this->mHwc = pdev;
75 mOtfMode = OTF_OFF;
76 mUseSubtitles = false;
77
78 mMPPs[0] = new ExynosMPPModule(this, HDMI_GSC_IDX);
79 memset(mMixerLayers, 0, sizeof(mMixerLayers));
80 memset(mLastLayerHandles, 0, sizeof(mLastLayerHandles));
81}
82
83ExynosExternalDisplay::~ExynosExternalDisplay()
84{
85 delete mMPPs[0];
86}
87
88int ExynosExternalDisplay::openHdmi()
89{
90 int ret = 0;
91 int sw_fd;
92
93 mMixer = exynos_subdev_open_devname("s5p-mixer0", O_RDWR);
94 if (mMixer < 0) {
95 ALOGE("failed to open hdmi mixer0 subdev");
96 ret = mMixer;
97 return ret;
98 }
99
100#if defined(USE_GRALLOC_FLAG_FOR_HDMI)
101 mUiIndex = 1;
102 mVideoIndex = 0;
103#else
104 mUiIndex = 0;
105 mVideoIndex = 1;
106#endif
107
108 mMixerLayers[0].id = 0;
109 mMixerLayers[0].fd = open("/dev/video16", O_RDWR);
110 if (mMixerLayers[0].fd < 0) {
111 ALOGE("failed to open hdmi layer0 device");
112 ret = mMixerLayers[0].fd;
113 close(mMixer);
114 return ret;
115 }
116
117 mMixerLayers[1].id = 1;
118 mMixerLayers[1].fd = open("/dev/video17", O_RDWR);
119 if (mMixerLayers[1].fd < 0) {
120 ALOGE("failed to open hdmi layer1 device");
121 ret = mMixerLayers[1].fd;
122 close(mMixerLayers[0].fd);
123 return ret;
124 }
125
126#if defined(VP_VIDEO)
127 mMixerLayers[2].id = VIDEO_LAYER_INDEX;
128 mMixerLayers[2].fd = open("/dev/video20", O_RDWR);
129 if (mMixerLayers[2].fd < 0) {
130 ALOGE("failed to open hdmi video layer device");
131 ret = mMixerLayers[2].fd;
132 close(mMixerLayers[0].fd);
133 close(mMixerLayers[1].fd);
134 return ret;
135 }
136#else
137 mMixerLayers[2].id = VIDEO_LAYER_INDEX;
138 mMixerLayers[2].fd = -1;
139#endif
140 return ret;
141}
142
143void ExynosExternalDisplay::setHdmiStatus(bool status)
144{
145 if (status) {
146 enable();
147 } else {
148 disable();
149 }
150}
151
152bool ExynosExternalDisplay::isPresetSupported(unsigned int preset)
153{
154#if defined(USE_DV_TIMINGS)
155 struct v4l2_enum_dv_timings enum_timings;
156 int dv_timings_index = getDVTimingsIndex(preset);
157#else
158 struct v4l2_dv_enum_preset enum_preset;
159#endif
160 bool found = false;
161 int index = 0;
162 int ret;
163
164 if (preset <= V4L2_DV_INVALID || preset > V4L2_DV_1080P30_TB) {
165 ALOGE("%s: invalid preset, %d", __func__, preset);
166 return -1;
167 }
168#if defined(USE_DV_TIMINGS)
169 if (dv_timings_index < 0) {
170 ALOGE("%s: unsupported preset, %d", __func__, preset);
171 return -1;
172 }
173#endif
174
175 while (true) {
176#if defined(USE_DV_TIMINGS)
177 enum_timings.index = index++;
178 ret = ioctl(mMixerLayers[0].fd, VIDIOC_ENUM_DV_TIMINGS, &enum_timings);
179
180 if (ret < 0) {
181 if (errno == EINVAL)
182 break;
183 ALOGE("%s: enum_dv_timings error, %d", __func__, errno);
184 return -1;
185 }
186
187 ALOGV("%s: %d width=%d height=%d",
188 __func__, enum_timings.index,
189 enum_timings.timings.bt.width, enum_timings.timings.bt.height);
190
191 if (is_same_dv_timings(&enum_timings.timings, &dv_timings[dv_timings_index])) {
192 mXres = enum_timings.timings.bt.width;
193 mYres = enum_timings.timings.bt.height;
194 found = true;
195 mHwc->mHdmiCurrentPreset = preset;
196 }
197#else
198 enum_preset.index = index++;
199 ret = ioctl(mMixerLayers[0].fd, VIDIOC_ENUM_DV_PRESETS, &enum_preset);
200
201 if (ret < 0) {
202 if (errno == EINVAL)
203 break;
204 ALOGE("%s: enum_dv_presets error, %d", __func__, errno);
205 return -1;
206 }
207
208 ALOGV("%s: %d preset=%02d width=%d height=%d name=%s",
209 __func__, enum_preset.index, enum_preset.preset,
210 enum_preset.width, enum_preset.height, enum_preset.name);
211
212 if (preset == enum_preset.preset) {
213 mXres = enum_preset.width;
214 mYres = enum_preset.height;
215 found = true;
216 mHwc->mHdmiCurrentPreset = preset;
217 }
218#endif
219 }
220 return found;
221}
222
223int ExynosExternalDisplay::getConfig()
224{
225#if defined(USE_DV_TIMINGS)
226 struct v4l2_dv_timings timings;
227 int dv_timings_index = 0;
228#endif
229 struct v4l2_dv_preset preset;
230 int ret;
231
232 if (!mHwc->hdmi_hpd)
233 return -1;
234
235#if defined(USE_DV_TIMINGS)
236 if (ioctl(mMixerLayers[0].fd, VIDIOC_G_DV_TIMINGS, &timings) < 0) {
237 ALOGE("%s: g_dv_timings error, %d", __func__, errno);
238 return -1;
239 }
240 for (int i = 0; i < SUPPORTED_DV_TIMINGS_NUM; i++) {
241 dv_timings_index = preset_index_mappings[i].dv_timings_index;
242 if (is_same_dv_timings(&timings, &dv_timings[dv_timings_index])) {
243 preset.preset = preset_index_mappings[i].preset;
244 break;
245 }
246 }
247#else
248 if (ioctl(mMixerLayers[0].fd, VIDIOC_G_DV_PRESET, &preset) < 0) {
249 ALOGE("%s: g_dv_preset error, %d", __func__, errno);
250 return -1;
251 }
252#endif
253
254 return isPresetSupported(preset.preset) ? 0 : -1;
255}
256
257int ExynosExternalDisplay::getDisplayConfigs(uint32_t *configs, size_t *numConfigs)
258{
259 *numConfigs = 1;
260 configs[0] = 0;
261 getConfig();
262 return 0;
263}
264
265int ExynosExternalDisplay::enableLayer(hdmi_layer_t &hl)
266{
267 if (hl.enabled)
268 return 0;
269
270 struct v4l2_requestbuffers reqbuf;
271 memset(&reqbuf, 0, sizeof(reqbuf));
272 reqbuf.count = NUM_HDMI_BUFFERS;
273 reqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
274 reqbuf.memory = V4L2_MEMORY_DMABUF;
275 if (exynos_v4l2_reqbufs(hl.fd, &reqbuf) < 0) {
276 ALOGE("%s: layer%d: reqbufs failed %d", __func__, hl.id, errno);
277 return -1;
278 }
279
280 if (reqbuf.count != NUM_HDMI_BUFFERS) {
281 ALOGE("%s: layer%d: didn't get buffer", __func__, hl.id);
282 return -1;
283 }
284
285 if (hl.id == mUiIndex) {
286 if (exynos_v4l2_s_ctrl(hl.fd, V4L2_CID_TV_PIXEL_BLEND_ENABLE, 1) < 0) {
287 ALOGE("%s: layer%d: PIXEL_BLEND_ENABLE failed %d", __func__,
288 hl.id, errno);
289 return -1;
290 }
291 } else {
292 if (exynos_v4l2_s_ctrl(hl.fd, V4L2_CID_TV_PIXEL_BLEND_ENABLE, 0) < 0) {
293 ALOGE("%s: layer%d: PIXEL_BLEND_DISABLE failed %d", __func__,
294 hl.id, errno);
295 return -1;
296 }
297 }
298
299 ALOGV("%s: layer%d enabled", __func__, hl.id);
300 hl.enabled = true;
301 return 0;
302}
303
304void ExynosExternalDisplay::disableLayer(hdmi_layer_t &hl)
305{
306 if (!hl.enabled)
307 return;
308
309 if (hl.streaming) {
310 if (exynos_v4l2_streamoff(hl.fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) < 0)
311 ALOGE("%s: layer%d: streamoff failed %d", __func__, hl.id, errno);
312 hl.streaming = false;
313 }
314
315 struct v4l2_requestbuffers reqbuf;
316 memset(&reqbuf, 0, sizeof(reqbuf));
317 reqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
318 reqbuf.memory = V4L2_MEMORY_DMABUF;
319 if (exynos_v4l2_reqbufs(hl.fd, &reqbuf) < 0)
320 ALOGE("%s: layer%d: reqbufs failed %d", __func__, hl.id, errno);
321
322 memset(&hl.cfg, 0, sizeof(hl.cfg));
323 hl.current_buf = 0;
324 hl.queued_buf = 0;
325 hl.enabled = false;
326
327 ALOGV("%s: layer%d disabled", __func__, hl.id);
328}
329
330int ExynosExternalDisplay::enable()
331{
332 if (mEnabled)
333 return 0;
334
335 if (mBlanked)
336 return 0;
337
338 struct v4l2_subdev_format sd_fmt;
339 memset(&sd_fmt, 0, sizeof(sd_fmt));
340 sd_fmt.pad = MIXER_G0_SUBDEV_PAD_SINK;
341 sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
342 sd_fmt.format.width = mXres;
343 sd_fmt.format.height = mYres;
344 sd_fmt.format.code = V4L2_MBUS_FMT_XRGB8888_4X8_LE;
345 if (exynos_subdev_s_fmt(mMixer, &sd_fmt) < 0) {
346 ALOGE("%s: s_fmt failed pad=%d", __func__, sd_fmt.pad);
347 return -1;
348 }
349
350 struct v4l2_subdev_crop sd_crop;
351 memset(&sd_crop, 0, sizeof(sd_crop));
352 sd_crop.pad = MIXER_G0_SUBDEV_PAD_SINK;
353 sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
354 sd_crop.rect.width = mXres;
355 sd_crop.rect.height = mYres;
356 if (exynos_subdev_s_crop(mMixer, &sd_crop) < 0) {
357 ALOGE("%s: s_crop failed pad=%d", __func__, sd_crop.pad);
358 return -1;
359 }
360
361 memset(&sd_fmt, 0, sizeof(sd_fmt));
362 sd_fmt.pad = MIXER_G0_SUBDEV_PAD_SOURCE;
363 sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
364 sd_fmt.format.width = mXres;
365 sd_fmt.format.height = mYres;
366 sd_fmt.format.code = V4L2_MBUS_FMT_XRGB8888_4X8_LE;
367 if (exynos_subdev_s_fmt(mMixer, &sd_fmt) < 0) {
368 ALOGE("%s: s_fmt failed pad=%d", __func__, sd_fmt.pad);
369 return -1;
370 }
371
372 memset(&sd_crop, 0, sizeof(sd_crop));
373 sd_crop.pad = MIXER_G0_SUBDEV_PAD_SOURCE;
374 sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
375 sd_crop.rect.width = mXres;
376 sd_crop.rect.height = mYres;
377 if (exynos_subdev_s_crop(mMixer, &sd_crop) < 0) {
378 ALOGE("%s: s_crop failed pad=%d", __func__, sd_crop.pad);
379 return -1;
380 }
381
382 char value[PROPERTY_VALUE_MAX];
383 property_get("persist.hdmi.hdcp_enabled", value, "1");
384 int hdcp_enabled = atoi(value);
385
386 if (exynos_v4l2_s_ctrl(mMixerLayers[mUiIndex].fd, V4L2_CID_TV_HDCP_ENABLE,
387 hdcp_enabled) < 0)
388 ALOGE("%s: s_ctrl(CID_TV_HDCP_ENABLE) failed %d", __func__, errno);
389
390 /* "2" is RGB601_16_235 */
391 property_get("persist.hdmi.color_range", value, "2");
392 int color_range = atoi(value);
393
394 if (exynos_v4l2_s_ctrl(mMixerLayers[mUiIndex].fd, V4L2_CID_TV_SET_COLOR_RANGE,
395 color_range) < 0)
396 ALOGE("%s: s_ctrl(CID_TV_COLOR_RANGE) failed %d", __func__, errno);
397
398 enableLayer(mMixerLayers[mUiIndex]);
399
400 mEnabled = true;
401 return 0;
402}
403
404void ExynosExternalDisplay::disable()
405{
406 if (!mEnabled)
407 return;
408
409 disableLayer(mMixerLayers[0]);
410 disableLayer(mMixerLayers[1]);
411#if defined(VP_VIDEO)
412 disableLayer(mMixerLayers[2]);
413#endif
414
415 blank();
416
417 mMPPs[0]->cleanupM2M();
418 mEnabled = false;
419}
420
421int ExynosExternalDisplay::output(hdmi_layer_t &hl,
422 hwc_layer_1_t &layer,
423 private_handle_t *h,
424 int acquireFenceFd,
425 int *releaseFenceFd)
426{
427 int ret = 0;
428
429 exynos_mpp_img src_cfg;
430 memset(&src_cfg, 0, sizeof(src_cfg));
431
432 if (hl.id == VIDEO_LAYER_INDEX) {
433 src_cfg.x = layer.displayFrame.left;
434 src_cfg.y = layer.displayFrame.top;
435 src_cfg.w = WIDTH(layer.displayFrame);
436 src_cfg.h = HEIGHT(layer.displayFrame);
437#ifdef USES_DRM_SETTING_BY_DECON
438 src_cfg.drmMode = !!(getDrmMode(h->flags) == SECURE_DRM);
439#endif
440 if (isVPSupported(layer, h->format)) {
441 src_cfg.fw = h->stride;
442 src_cfg.fh = h->vstride;
443 } else {
444 src_cfg.fw = ALIGN(mXres, 16);
445 src_cfg.fh = ALIGN(mYres, 16);
446 }
447 }
448
449 exynos_mpp_img cfg;
450 memset(&cfg, 0, sizeof(cfg));
451 cfg.x = layer.displayFrame.left;
452 cfg.y = layer.displayFrame.top;
453 cfg.w = WIDTH(layer.displayFrame);
454 cfg.h = HEIGHT(layer.displayFrame);
455#ifdef USES_DRM_SETTING_BY_DECON
456 cfg.drmMode = !!(getDrmMode(h->flags) == SECURE_DRM);
457#endif
458
459 if ((signed int)cfg.x < 0 || (signed int)cfg.y < 0 || (cfg.w > (uint32_t)mXres) || (cfg.h > (uint32_t)mYres)) {
460 *releaseFenceFd = -1;
461 if (acquireFenceFd >= 0)
462 close(acquireFenceFd);
463 return ret;
464 }
465
466 if ((hl.id == VIDEO_LAYER_INDEX && ExynosMPP::isSrcConfigChanged(hl.cfg, src_cfg)) ||
467 (hl.id != VIDEO_LAYER_INDEX && ExynosMPP::isSrcConfigChanged(hl.cfg, cfg)) || mFbStarted || mVideoStarted) {
468 struct v4l2_subdev_crop sd_crop;
469 memset(&sd_crop, 0, sizeof(sd_crop));
470 if (hl.id == 0)
471 sd_crop.pad = MIXER_G0_SUBDEV_PAD_SOURCE;
472 else if (hl.id == 1)
473 sd_crop.pad = MIXER_G1_SUBDEV_PAD_SOURCE;
474
475 if ((hl.id == VIDEO_LAYER_INDEX && hdmi_src_cfg_changed(hl.cfg, src_cfg)) ||
476 (hl.id != VIDEO_LAYER_INDEX && hdmi_src_cfg_changed(hl.cfg, cfg)) || mFbStarted || mVideoStarted) {
477 disableLayer(hl);
478
479 /* Set source image size */
480 struct v4l2_format fmt;
481 memset(&fmt, 0, sizeof(fmt));
482 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
483
484 if (hl.id == VIDEO_LAYER_INDEX) {
485 if (isVPSupported(layer, h->format)) {
486 fmt.fmt.pix_mp.width = h->stride;
487 fmt.fmt.pix_mp.height = h->vstride;
488 } else {
489 fmt.fmt.pix_mp.width = ALIGN(mXres, 16);
490 fmt.fmt.pix_mp.height = ALIGN(mYres, 16);
491 }
492 } else if (hl.id == mVideoIndex) {
493 fmt.fmt.pix_mp.width = ALIGN(mXres, 16);
494 fmt.fmt.pix_mp.height = ALIGN(mYres, 16);
495 } else {
496 fmt.fmt.pix_mp.width = h->stride;
497 fmt.fmt.pix_mp.height = h->vstride;
498 }
499
500 if (hl.id == VIDEO_LAYER_INDEX) {
501 if (isVPSupported(layer, h->format))
502 fmt.fmt.pix_mp.pixelformat = HAL_PIXEL_FORMAT_2_V4L2_PIX(h->format);
503 else
504 fmt.fmt.pix_mp.pixelformat = HAL_PIXEL_FORMAT_2_V4L2_PIX(HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED);
505 fmt.fmt.pix_mp.num_planes = 2;
506 } else {
507 fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_BGR32;
508 fmt.fmt.pix_mp.num_planes = 1;
509 }
510 fmt.fmt.pix_mp.field = V4L2_FIELD_ANY;
511
512 ret = exynos_v4l2_s_fmt(hl.fd, &fmt);
513 if (ret < 0) {
514 ALOGE("%s: layer%d: s_fmt failed %d", __func__, hl.id, errno);
515 goto err;
516 }
517
518 if (hl.id != VIDEO_LAYER_INDEX) {
519 struct v4l2_subdev_format sd_fmt;
520 memset(&sd_fmt, 0, sizeof(sd_fmt));
521 sd_fmt.pad = sd_crop.pad;
522 sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
523 sd_fmt.format.width = mXres;
524 sd_fmt.format.height = mYres;
525 sd_fmt.format.code = V4L2_MBUS_FMT_XRGB8888_4X8_LE;
526 if (exynos_subdev_s_fmt(mMixer, &sd_fmt) < 0) {
527 ALOGE("%s: s_fmt failed pad=%d", __func__, sd_fmt.pad);
528 return -1;
529 }
530 }
531
532 enableLayer(hl);
533
534 mFbStarted = false;
535 mVideoStarted = false;
536 }
537
538 /* Set source crop size */
539 struct v4l2_crop crop;
540 memset(&crop, 0, sizeof(crop));
541 crop.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
542 crop.c.width = cfg.w;
543 crop.c.height = cfg.h;
544
545 if (hl.id == VIDEO_LAYER_INDEX) {
546 if (isVPSupported(layer, h->format)) {
547 crop.c.left = layer.sourceCropf.left;
548 crop.c.top = layer.sourceCropf.top;
549 crop.c.width = WIDTH(layer.sourceCropf);
550 crop.c.height = HEIGHT(layer.sourceCropf);
551 } else {
552 crop.c.left = 0;
553 crop.c.top = 0;
554 }
555 } else if (hl.id == mVideoIndex) {
556 crop.c.left = 0;
557 crop.c.top = 0;
558 } else {
559 crop.c.left = cfg.x;
560 crop.c.top = cfg.y;
561 }
562
563 if (exynos_v4l2_s_crop(hl.fd, &crop) < 0) {
564 ALOGE("%s: v4l2_s_crop failed ", __func__);
565 goto err;
566 }
567
568 /* Set destination position & scaling size */
569 if (hl.id == VIDEO_LAYER_INDEX) {
570 crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
571 crop.c.left = cfg.x;
572 crop.c.top = cfg.y;
573 crop.c.width = cfg.w;
574 crop.c.height = cfg.h;
575
576 if (exynos_v4l2_s_crop(hl.fd, &crop) < 0) {
577 ALOGE("%s: v4l2_s_crop (mixer output) failed ", __func__);
578 goto err;
579 }
580 } else {
581 sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
582 sd_crop.rect.left = cfg.x;
583 sd_crop.rect.top = cfg.y;
584 sd_crop.rect.width = cfg.w;
585 sd_crop.rect.height = cfg.h;
586 if (exynos_subdev_s_crop(mMixer, &sd_crop) < 0) {
587 ALOGE("%s: s_crop failed pad=%d", __func__, sd_crop.pad);
588 goto err;
589 }
590 }
591
592 ALOGV("HDMI layer%d configuration:", hl.id);
593 dumpMPPImage(cfg);
594 if (hl.id == VIDEO_LAYER_INDEX)
595 hl.cfg = src_cfg;
596 else
597 hl.cfg = cfg;
598 }
599
600 struct v4l2_buffer buffer;
601 struct v4l2_plane planes[3];
602
603 if (hl.queued_buf == NUM_HDMI_BUFFERS) {
604 memset(&buffer, 0, sizeof(buffer));
605 memset(planes, 0, sizeof(planes));
606 buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
607 buffer.memory = V4L2_MEMORY_DMABUF;
608 if(hl.id == VIDEO_LAYER_INDEX)
609 buffer.length = 2;
610 else
611 buffer.length = 1;
612 buffer.m.planes = planes;
613 ret = exynos_v4l2_dqbuf(hl.fd, &buffer);
614 if (ret < 0) {
615 ALOGE("%s: layer%d: dqbuf failed %d", __func__, hl.id, errno);
616 goto err;
617 }
618 hl.queued_buf--;
619 }
620
621 memset(&buffer, 0, sizeof(buffer));
622 memset(planes, 0, sizeof(planes));
623 buffer.index = hl.current_buf;
624 buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
625 buffer.memory = V4L2_MEMORY_DMABUF;
626 buffer.flags = V4L2_BUF_FLAG_USE_SYNC;
627 buffer.reserved = acquireFenceFd;
628 buffer.m.planes = planes;
629
630
631 if (hl.id == VIDEO_LAYER_INDEX) {
632 buffer.length = 2;
633 buffer.m.planes[0].m.fd = h->fd;
634 buffer.m.planes[1].m.fd = h->fd1;
635 } else {
636 buffer.length = 1;
637 buffer.m.planes[0].m.fd = h->fd;
638 }
639
640 if (exynos_v4l2_qbuf(hl.fd, &buffer) < 0) {
641 ALOGE("%s: layer%d: qbuf failed %d", __func__, hl.id, errno);
642 ret = -1;
643 goto err;
644 }
645
646 if (releaseFenceFd)
647 *releaseFenceFd = buffer.reserved;
648 else
649 close(buffer.reserved);
650
651 hl.queued_buf++;
652 hl.current_buf = (hl.current_buf + 1) % NUM_HDMI_BUFFERS;
653
654 if (!hl.streaming) {
655#ifdef USES_DRM_SETTING_BY_DECON
656 if (exynos_v4l2_s_ctrl(hl.fd, V4L2_CID_CONTENT_PROTECTION, hl.cfg.drmMode) < 0)
657 ALOGE("%s: s_ctrl(V4L2_CID_CONTENT_PROTECTION) failed %d", __func__, errno);;
658#endif
659 if (exynos_v4l2_streamon(hl.fd, (v4l2_buf_type)buffer.type) < 0) {
660 ALOGE("%s: layer%d: streamon failed %d", __func__, hl.id, errno);
661 ret = -1;
662 goto err;
663 }
664 hl.streaming = true;
665 }
666
667err:
668 if (acquireFenceFd >= 0)
669 close(acquireFenceFd);
670
671 return ret;
672}
673
674void ExynosExternalDisplay::skipStaticLayers(hwc_display_contents_1_t *contents, int ovly_idx)
675{
676 static int init_flag = 0;
677 mVirtualOverlayFlag = 0;
678 mHasSkipLayer = false;
679
680 if (contents->flags & HWC_GEOMETRY_CHANGED) {
681 init_flag = 0;
682 return;
683 }
684
685 if ((ovly_idx == -1) || (ovly_idx >= ((int)contents->numHwLayers - 2)) ||
686 ((contents->numHwLayers - ovly_idx - 1) >= NUM_VIRT_OVER_HDMI)) {
687 init_flag = 0;
688 return;
689 }
690
691 ovly_idx++;
692 if (init_flag == 1) {
693 for (size_t i = ovly_idx; i < contents->numHwLayers - 1; i++) {
694 hwc_layer_1_t &layer = contents->hwLayers[i];
695 if (!layer.handle || (mLastLayerHandles[i - ovly_idx] != layer.handle)) {
696 init_flag = 0;
697 return;
698 }
699 }
700
701 mVirtualOverlayFlag = 1;
702 for (size_t i = ovly_idx; i < contents->numHwLayers - 1; i++) {
703 hwc_layer_1_t &layer = contents->hwLayers[i];
704 if (layer.compositionType == HWC_FRAMEBUFFER) {
705 layer.compositionType = HWC_OVERLAY;
706 mHasSkipLayer = true;
707 }
708 }
709 return;
710 }
711
712 init_flag = 1;
713 for (size_t i = ovly_idx; i < contents->numHwLayers; i++) {
714 hwc_layer_1_t &layer = contents->hwLayers[i];
715 mLastLayerHandles[i - ovly_idx] = layer.handle;
716 }
717
718 for (size_t i = contents->numHwLayers - ovly_idx; i < NUM_VIRT_OVER_HDMI; i++)
719 mLastLayerHandles[i - ovly_idx] = 0;
720
721 return;
722}
723
724void ExynosExternalDisplay::setPreset(int preset)
725{
726 mHwc->mHdmiResolutionChanged = false;
727 mHwc->mHdmiResolutionHandled = false;
728 mHwc->hdmi_hpd = false;
729#if !defined(USE_DV_TIMINGS)
730 v4l2_dv_preset v_preset;
731 v_preset.preset = preset;
732#else
733 struct v4l2_dv_timings dv_timing;
734 int dv_timings_index = getDVTimingsIndex(preset);
735 if (dv_timings_index < 0) {
736 ALOGE("invalid preset(%d)", preset);
737 return;
738 }
739 memcpy(&dv_timing, &dv_timings[dv_timings_index], sizeof(v4l2_dv_timings));
740#endif
741
742 if (preset <= V4L2_DV_INVALID || preset > V4L2_DV_1080P30_TB) {
743 ALOGE("%s: invalid preset, %d", __func__, preset);
744 return;
745 }
746
747 disable();
748#if defined(USE_DV_TIMINGS)
749 if (ioctl(mMixerLayers[0].fd, VIDIOC_S_DV_TIMINGS, &dv_timing) != -1) {
750 if (mHwc->procs)
751 mHwc->procs->hotplug(mHwc->procs, HWC_DISPLAY_EXTERNAL, false);
752 }
753#else
754 if (ioctl(mMixerLayers[0].fd, VIDIOC_S_DV_PRESET, &v_preset) != -1) {
755 if (mHwc->procs)
756 mHwc->procs->hotplug(mHwc->procs, HWC_DISPLAY_EXTERNAL, false);
757 }
758#endif
759}
760
761int ExynosExternalDisplay::convert3DTo2D(int preset)
762{
763 switch (preset) {
764 case V4L2_DV_720P60_FP:
765 case V4L2_DV_720P60_SB_HALF:
766 case V4L2_DV_720P60_TB:
767 return V4L2_DV_720P60;
768 case V4L2_DV_720P50_FP:
769 case V4L2_DV_720P50_SB_HALF:
770 case V4L2_DV_720P50_TB:
771 return V4L2_DV_720P50;
772 case V4L2_DV_1080P60_SB_HALF:
773 case V4L2_DV_1080P60_TB:
774 return V4L2_DV_1080P60;
775 case V4L2_DV_1080P30_FP:
776 case V4L2_DV_1080P30_SB_HALF:
777 case V4L2_DV_1080P30_TB:
778 return V4L2_DV_1080P30;
779 default:
780 return HDMI_PRESET_ERROR;
781 }
782}
783
784void ExynosExternalDisplay::calculateDstRect(int src_w, int src_h, int dst_w, int dst_h, struct v4l2_rect *dst_rect)
785{
786 if (dst_w * src_h <= dst_h * src_w) {
787 dst_rect->left = 0;
788 dst_rect->top = (dst_h - ((dst_w * src_h) / src_w)) >> 1;
789 dst_rect->width = dst_w;
790 dst_rect->height = ((dst_w * src_h) / src_w);
791 } else {
792 dst_rect->left = (dst_w - ((dst_h * src_w) / src_h)) >> 1;
793 dst_rect->top = 0;
794 dst_rect->width = ((dst_h * src_w) / src_h);
795 dst_rect->height = dst_h;
796 }
797}
798
799bool ExynosExternalDisplay::isVPSupported(hwc_layer_1_t &layer, int format)
800{
801#if defined(VP_VIDEO)
802 int min_source_width = 32;
803 int min_source_height = 4;
804 private_handle_t *h = private_handle_t::dynamicCast(layer.handle);
805 if((layer.transform == 0) &&
806 (format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED ||
807 format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M ||
808 format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV ||
809 format == HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M)) {
810 if (h->stride >= min_source_width &&
811 h->height >= min_source_height &&
812 (WIDTH(layer.sourceCropf) == WIDTH(layer.displayFrame)) &&
813 (HEIGHT(layer.sourceCropf) == HEIGHT(layer.displayFrame))) {
814 return true;
815 }
816 }
817#endif
818 return false;
819}
820
821bool ExynosExternalDisplay::isVideoOverlaySupported(hwc_layer_1_t &layer, int format)
822{
823#if defined(VP_VIDEO)
824 if (isVPSupported(layer, format))
825 return true;
826#endif
827 if (mMPPs[0]->isProcessingSupported(layer, format, false) > 0)
828 return true;
829
830 return false;
831}
832
833int ExynosExternalDisplay::prepare(hwc_display_contents_1_t* contents)
834{
835 hwc_layer_1_t *video_layer = NULL;
836 uint32_t numVideoLayers = 0;
837 uint32_t videoIndex = 0;
838
839 mHwc->force_mirror_mode = false;
840 checkGrallocFlags(contents);
841
842 for (size_t i = 0; i < contents->numHwLayers; i++) {
843 hwc_layer_1_t &layer = contents->hwLayers[i];
844
845 if (layer.compositionType == HWC_FRAMEBUFFER_TARGET) {
846 ALOGV("\tlayer %u: framebuffer target", i);
847 continue;
848 }
849
850 if (layer.compositionType == HWC_BACKGROUND) {
851 ALOGV("\tlayer %u: background layer", i);
852 dumpLayer(&layer);
853 continue;
854 }
855
856#if defined(USE_GRALLOC_FLAG_FOR_HDMI)
857 if (mLocalExternalDisplayPause) {
858 layer.compositionType = HWC_OVERLAY;
859 layer.flags = HWC_SKIP_HDMI_RENDERING;
860 continue;
861 }
862#endif
863
864 if (layer.handle) {
865 private_handle_t *h = private_handle_t::dynamicCast(layer.handle);
866 if ((int)get_yuv_planes(halFormatToV4L2Format(h->format)) > 0) {
867 if (mHwc->mS3DMode != S3D_MODE_DISABLED && mHwc->mHdmiResolutionChanged)
868 mHwc->mS3DMode = S3D_MODE_RUNNING;
869 }
870
871 if ((mHwc->force_mirror_mode) && getDrmMode(h->flags) == NO_DRM) {
872 layer.compositionType = HWC_FRAMEBUFFER;
873 continue;
874 } else {
875#if defined(GSC_VIDEO) || defined(VP_VIDEO)
876 if (((getDrmMode(h->flags) != NO_DRM)
877 || ((int)get_yuv_planes(halFormatToV4L2Format(h->format)) > 0)) &&
878 isVideoOverlaySupported(layer, h->format)) {
879#else
880 if (getDrmMode(h->flags) != NO_DRM) {
881#endif
882#if !defined(GSC_VIDEO) && !defined(VP_VIDEO)
883 if (((mUseProtectedLayer == true) && (getDrmMode(handle->flags) != NO_DRM)) ||
884 ((mUseProtectedLayer == false) && !video_layer)) {
885#endif
886 video_layer = &layer;
887 layer.compositionType = HWC_OVERLAY;
888#if defined(GSC_VIDEO) || defined(VP_VIDEO)
889 videoIndex = i;
890 numVideoLayers++;
891#endif
892 ALOGV("\tlayer %u: video layer", i);
893 dumpLayer(&layer);
894 continue;
895#if !defined(GSC_VIDEO) && !defined(VP_VIDEO)
896 }
897#endif
898 }
899 }
900 layer.compositionType = HWC_FRAMEBUFFER;
901 dumpLayer(&layer);
902 } else {
903 layer.compositionType = HWC_FRAMEBUFFER;
904 }
905 }
906#if defined(GSC_VIDEO) || defined(VP_VIDEO)
907 if (numVideoLayers == 1) {
908 for (size_t i = 0; i < contents->numHwLayers; i++) {
909 hwc_layer_1_t &layer = contents->hwLayers[i];
910 if (!mUseSubtitles || i == videoIndex) {
911 if (mHwc->mS3DMode != S3D_MODE_DISABLED)
912 layer.compositionType = HWC_OVERLAY;
913 }
914
915 if (i == videoIndex) {
916 struct v4l2_rect dest_rect;
917 if (mHwc->mS3DMode != S3D_MODE_DISABLED) {
918 layer.displayFrame.left = 0;
919 layer.displayFrame.top = 0;
920 layer.displayFrame.right = mXres;
921 layer.displayFrame.bottom = mYres;
922 }
923 }
924 }
925#if !defined(USE_GRALLOC_FLAG_FOR_HDMI)
926 skipStaticLayers(contents, videoIndex);
927#endif
928 } else if (numVideoLayers > 1) {
929 for (size_t i = 0; i < contents->numHwLayers; i++) {
930 hwc_layer_1_t &layer = contents->hwLayers[i];
931 private_handle_t *handle = NULL;
932 if (layer.handle) {
933 handle = private_handle_t::dynamicCast(layer.handle);
934 if (getDrmMode(handle->flags) != NO_DRM)
935 continue;
936 }
937 if (layer.compositionType == HWC_FRAMEBUFFER_TARGET ||
938 layer.compositionType == HWC_BACKGROUND)
939 continue;
940 layer.compositionType = HWC_FRAMEBUFFER;
941 }
942 }
943#endif
944 mHasFbComposition = false;
945 for (size_t i = 0; i < contents->numHwLayers; i++) {
946 hwc_layer_1_t &layer = contents->hwLayers[i];
947 if (layer.compositionType == HWC_FRAMEBUFFER)
948 mHasFbComposition = true;
949 }
950 return 0;
951}
952
953int ExynosExternalDisplay::clearDisplay()
954{
955 return -1;
956}
957
958int ExynosExternalDisplay::set(hwc_display_contents_1_t* contents)
959{
960 hwc_layer_1_t *fb_layer = NULL;
961 hwc_layer_1_t *video_layer = NULL;
962
963 if (!mEnabled || mBlanked) {
964 for (size_t i = 0; i < contents->numHwLayers; i++) {
965 hwc_layer_1_t &layer = contents->hwLayers[i];
966 if (layer.acquireFenceFd >= 0) {
967 close(layer.acquireFenceFd);
968 layer.acquireFenceFd = -1;
969 }
970 }
971 return 0;
972 }
973
974#if !defined(USE_GRALLOC_FLAG_FOR_HDMI)
975#if defined(VP_VIDEO)
976 mVideoIndex = VIDEO_LAYER_INDEX;
977#else
978 mVideoIndex = 1;
979#endif
980 mUiIndex = 0;
981#endif
982
983 for (size_t i = 0; i < contents->numHwLayers; i++) {
984 hwc_layer_1_t &layer = contents->hwLayers[i];
985
986 if (layer.flags & HWC_SKIP_LAYER) {
987 ALOGV("HDMI skipping layer %d", i);
988 continue;
989 }
990
991 if (layer.compositionType == HWC_OVERLAY) {
992 if (!layer.handle) {
993 layer.releaseFenceFd = layer.acquireFenceFd;
994 continue;
995 }
996
997#if defined(USE_GRALLOC_FLAG_FOR_HDMI)
998 if (layer.flags & HWC_SKIP_HDMI_RENDERING) {
999 layer.releaseFenceFd = layer.acquireFenceFd;
1000 continue;
1001 } else {
1002#endif
1003#if defined(GSC_VIDEO) || defined(VP_VIDEO)
1004 private_handle_t *handle = private_handle_t::dynamicCast(layer.handle);
1005 if ((int)get_yuv_planes(halFormatToV4L2Format(handle->format)) < 0) {
1006 layer.releaseFenceFd = layer.acquireFenceFd;
1007 continue;
1008 }
1009#endif
1010#if defined(USE_GRALLOC_FLAG_FOR_HDMI)
1011 }
1012#endif
1013
1014 ALOGV("HDMI video layer:");
1015 dumpLayer(&layer);
1016
1017 int gsc_idx = HDMI_GSC_IDX;
1018 bool changedPreset = false;
1019 if (mHwc->mS3DMode != S3D_MODE_DISABLED && mHwc->mHdmiResolutionChanged) {
1020 if (isPresetSupported(mHwc->mHdmiPreset)) {
1021 mHwc->mS3DMode = S3D_MODE_RUNNING;
1022 setPreset(mHwc->mHdmiPreset);
1023 changedPreset = true;
1024 } else {
1025 mHwc->mS3DMode = S3D_MODE_RUNNING;
1026 mHwc->mHdmiResolutionChanged = false;
1027 mHwc->mHdmiResolutionHandled = true;
1028 int S3DFormat = getS3DFormat(mHwc->mHdmiPreset);
1029 if (S3DFormat == S3D_SBS)
1030 mMPPs[0]->mS3DMode = S3D_SBS;
1031 else if (S3DFormat == S3D_TB)
1032 mMPPs[0]->mS3DMode = S3D_TB;
1033 }
1034 }
1035 private_handle_t *h = private_handle_t::dynamicCast(layer.handle);
1036
1037#if defined(GSC_VIDEO) || defined(VP_VIDEO)
1038 if ((getDrmMode(h->flags) != NO_DRM) ||
1039 ((int)get_yuv_planes(halFormatToV4L2Format(h->format)) > 0)) {
1040#else
1041 if (getDrmMode(h->flags) != NO_DRM) {
1042#endif
1043 if (getDrmMode(h->flags) == SECURE_DRM)
1044 recalculateDisplayFrame(layer, mXres, mYres);
1045
1046 video_layer = &layer;
1047
1048 if (mIsVideoLayer == false)
1049 mVideoStarted = true;
1050 else
1051 mVideoStarted = false;
1052 mIsVideoLayer = true;
1053
1054#if defined(VP_VIDEO)
1055 if ((mMPPs[0]->mS3DMode == S3D_MODE_DISABLED) &&
1056 (isVPSupported(layer, h->format))) {
1057 enableLayer(mMixerLayers[mVideoIndex]);
1058 output(mMixerLayers[mVideoIndex], layer, h, layer.acquireFenceFd,
1059 &layer.releaseFenceFd);
1060 } else {
1061#endif
1062 ExynosMPPModule &gsc = *mMPPs[0];
1063#if defined(VP_VIDEO)
1064 int ret = gsc.processM2M(layer, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED, NULL);
1065#else
1066 int ret = gsc.processM2M(layer, HAL_PIXEL_FORMAT_BGRA_8888, NULL);
1067#endif
1068 if (ret < 0) {
1069 ALOGE("failed to configure gscaler for video layer");
1070 continue;
1071 }
1072
1073 buffer_handle_t dst_buf = gsc.mDstBuffers[gsc.mCurrentBuf];
1074 private_handle_t *h = private_handle_t::dynamicCast(dst_buf);
1075
1076 int acquireFenceFd = gsc.mDstConfig.releaseFenceFd;
1077 int releaseFenceFd = -1;
1078
1079 enableLayer(mMixerLayers[mVideoIndex]);
1080
1081 output(mMixerLayers[mVideoIndex], layer, h, acquireFenceFd,
1082 &releaseFenceFd);
1083
1084 if (gsc.mDstBufFence[gsc.mCurrentBuf] >= 0) {
1085 close (gsc.mDstBufFence[gsc.mCurrentBuf]);
1086 gsc.mDstBufFence[gsc.mCurrentBuf] = -1;
1087 }
1088 gsc.mDstBufFence[gsc.mCurrentBuf] = releaseFenceFd;
1089 gsc.mCurrentBuf = (gsc.mCurrentBuf + 1) % gsc.mNumAvailableDstBuffers;
1090#if defined(VP_VIDEO)
1091 }
1092#endif
1093 }
1094
1095 }
1096
1097 if (layer.compositionType == HWC_FRAMEBUFFER_TARGET) {
1098 if (!layer.handle) {
1099 layer.releaseFenceFd = layer.acquireFenceFd;
1100 continue;
1101 }
1102
1103 if (!mHasFbComposition && !mHasSkipLayer) {
1104 layer.releaseFenceFd = layer.acquireFenceFd;
1105 continue;
1106 }
1107
1108 dumpLayer(&layer);
1109
1110 /* HDMI rotation for camera preview */
1111 bool camera_preview_started = false;
1112 bool camera_connected = false;
1113 char value[PROPERTY_VALUE_MAX];
1114 property_get("persist.sys.camera.preview", value, "0");
1115 camera_preview_started = !!(atoi(value));
1116 property_get("persist.sys.camera.connect", value, "0");
1117 camera_connected = !!(atoi(value));
1118
1119 if (camera_preview_started && camera_connected)
1120 mIsCameraStarted = true;
1121 else if (!camera_preview_started && !camera_connected)
1122 mIsCameraStarted = false;
1123
1124 if (((mFBT_Transform == HAL_TRANSFORM_FLIP_V) ||
1125 (mFBT_Transform == HAL_TRANSFORM_FLIP_H) ||
1126 (mFBT_Transform == HAL_TRANSFORM_ROT_90) ||
1127 (mFBT_Transform == HAL_TRANSFORM_ROT_180) ||
1128 (mFBT_Transform == HAL_TRANSFORM_ROT_270))) {
1129 if (mHasFbComposition && mIsCameraStarted && camera_connected) {
1130 struct v4l2_rect dest_rect;
1131 bool rot90or270 = !!((mFBT_Transform) & HAL_TRANSFORM_ROT_90);
1132
1133 if (rot90or270)
1134 calculateDstRect(HEIGHT(layer.sourceCropf), WIDTH(layer.sourceCropf),
1135 mXres, mYres, &dest_rect);
1136 else
1137 calculateDstRect(WIDTH(layer.sourceCropf), HEIGHT(layer.sourceCropf),
1138 mXres, mYres, &dest_rect);
1139
1140 layer.displayFrame.left = dest_rect.left;
1141 layer.displayFrame.top = dest_rect.top;
1142 layer.displayFrame.right = dest_rect.width + dest_rect.left;
1143 layer.displayFrame.bottom = dest_rect.height + dest_rect.top;
1144 layer.transform = mFBT_Transform;
1145
1146 ExynosMPPModule &gsc = *mMPPs[0];
1147 int ret = gsc.processM2M(layer, HAL_PIXEL_FORMAT_BGRA_8888, NULL);
1148 if (ret < 0) {
1149 ALOGE("failed to configure gscaler for video layer");
1150 continue;
1151 }
1152
1153 buffer_handle_t dst_buf = gsc.mDstBuffers[gsc.mCurrentBuf];
1154 private_handle_t *h = private_handle_t::dynamicCast(dst_buf);
1155
1156 int acquireFenceFd = gsc.mDstConfig.releaseFenceFd;
1157 int releaseFenceFd = -1;
1158
1159 if (mIsVideoLayer == false)
1160 mVideoStarted = true;
1161 else
1162 mVideoStarted = false;
1163 mIsVideoLayer = true;
1164
1165 enableLayer(mMixerLayers[mVideoIndex]);
1166 output(mMixerLayers[mVideoIndex], layer, h, acquireFenceFd,
1167 &releaseFenceFd);
1168 if (gsc.mDstBufFence[gsc.mCurrentBuf] >= 0) {
1169 close (gsc.mDstBufFence[gsc.mCurrentBuf]);
1170 gsc.mDstBufFence[gsc.mCurrentBuf] = -1;
1171 }
1172 gsc.mDstBufFence[gsc.mCurrentBuf] = releaseFenceFd;
1173 gsc.mCurrentBuf = (gsc.mCurrentBuf + 1) % NUM_GSC_DST_BUFS;
1174
1175 } else
1176 layer.releaseFenceFd = layer.acquireFenceFd;
1177 video_layer = &layer;
1178 } else {
1179 if (mHasFbComposition && ((mIsCameraStarted && camera_connected) || !mIsCameraStarted)) {
1180 if (mIsFbLayer == false)
1181 mFbStarted = true;
1182 else
1183 mFbStarted = false;
1184 mIsFbLayer = true;
1185
1186 layer.displayFrame.left = 0;
1187 layer.displayFrame.right = mXres;
1188 layer.displayFrame.top = 0;
1189 layer.displayFrame.bottom = mYres;
1190 layer.transform = 0;
1191
1192 enableLayer(mMixerLayers[mUiIndex]);
1193 private_handle_t *h = private_handle_t::dynamicCast(layer.handle);
1194 private_module_t *grallocModule = (private_module_t *)((ExynosOverlayDisplay *)mHwc->primaryDisplay)->mGrallocModule;
1195 waitForRenderFinish(grallocModule, &layer.handle, 1);
1196 output(mMixerLayers[mUiIndex], layer, h, layer.acquireFenceFd,
1197 &layer.releaseFenceFd);
1198 } else
1199 layer.releaseFenceFd = layer.acquireFenceFd;
1200 fb_layer = &layer;
1201 }
1202 }
1203 }
1204
1205#if defined(USE_GRALLOC_FLAG_FOR_HDMI)
1206 if (!mLocalExternalDisplayPause) {
1207#endif
1208 if (!video_layer) {
1209 disableLayer(mMixerLayers[mVideoIndex]);
1210#if defined(USE_GRALLOC_FLAG_FOR_HDMI)
1211 mIsVideoLayer = false;
1212#endif
1213 mMPPs[0]->cleanupM2M();
1214 if (mHwc->mS3DMode == S3D_MODE_RUNNING && contents->numHwLayers > 1) {
1215 int preset = convert3DTo2D(mHwc->mHdmiCurrentPreset);
1216 if (isPresetSupported(preset)) {
1217 setPreset(preset);
1218 mHwc->mS3DMode = S3D_MODE_STOPPING;
1219 mHwc->mHdmiPreset = preset;
1220 if (mHwc->procs)
1221 mHwc->procs->invalidate(mHwc->procs);
1222 } else {
1223 mHwc->mS3DMode = S3D_MODE_DISABLED;
1224 mHwc->mHdmiPreset = mHwc->mHdmiCurrentPreset;
1225 }
1226 }
1227 }
1228
1229 if (!fb_layer) {
1230 disableLayer(mMixerLayers[mUiIndex]);
1231 mIsFbLayer = false;
1232 }
1233#if !defined(USE_GRALLOC_FLAG_FOR_HDMI)
1234 if (!video_layer) {
1235 disableLayer(mMixerLayers[mVideoIndex]);
1236 mIsVideoLayer = false;
1237 }
1238#endif
1239
1240 /* MIXER_UPDATE */
1241 if (exynos_v4l2_s_ctrl(mMixerLayers[mUiIndex].fd, V4L2_CID_TV_UPDATE, 1) < 0) {
1242 ALOGE("%s: s_ctrl(CID_TV_UPDATE) failed %d", __func__, errno);
1243 return -1;
1244 }
1245#if defined(USE_GRALLOC_FLAG_FOR_HDMI)
1246 }
1247#endif
1248
1249 return 0;
1250}
1251
1252void ExynosExternalDisplay::setHdcpStatus(int status)
1253{
1254 if (exynos_v4l2_s_ctrl(mMixerLayers[1].fd, V4L2_CID_TV_HDCP_ENABLE,
1255 !!status) < 0)
1256 ALOGE("%s: s_ctrl(CID_TV_HDCP_ENABLE) failed %d", __func__, errno);
1257}
1258
1259void ExynosExternalDisplay::setAudioChannel(uint32_t channels)
1260{
1261 if (exynos_v4l2_s_ctrl(mMixerLayers[0].fd,
1262 V4L2_CID_TV_SET_NUM_CHANNELS, channels) < 0)
1263 ALOGE("%s: failed to set audio channels", __func__);
1264}
1265
1266uint32_t ExynosExternalDisplay::getAudioChannel()
1267{
1268 int channels;
1269 if (exynos_v4l2_g_ctrl(mMixerLayers[0].fd,
1270 V4L2_CID_TV_MAX_AUDIO_CHANNELS, &channels) < 0)
1271 ALOGE("%s: failed to get audio channels", __func__);
1272 return channels;
1273}
1274
1275void ExynosExternalDisplay::checkGrallocFlags(hwc_display_contents_1_t *contents)
1276{
1277 mUseProtectedLayer = false;
1278#if defined(USE_GRALLOC_FLAG_FOR_HDMI)
1279 mUseScreenshootLayer = false;
1280
1281 /* it can get from HWCService */
1282 mLocalExternalDisplayPause = mHwc->external_display_pause;
1283 mFBT_Transform = mHwc->ext_fbt_transform;
1284#endif
1285
1286 for (size_t i = 0; i < contents->numHwLayers; i++) {
1287 hwc_layer_1_t &layer = contents->hwLayers[i];
1288 if (layer.handle) {
1289 private_handle_t *h = private_handle_t::dynamicCast(layer.handle);
1290 if (h->flags & GRALLOC_USAGE_PROTECTED)
1291 mUseProtectedLayer = false;
1292 }
1293#if defined(USE_GRALLOC_FLAG_FOR_HDMI)
1294 if (layer.flags & HWC_SCREENSHOT_ANIMATOR_LAYER)
1295 mUseScreenshootLayer = true;
1296#endif
1297 }
1298
1299#if defined(USE_GRALLOC_FLAG_FOR_HDMI)
1300 if (mUseScreenshootLayer)
1301 mLocalExternalDisplayPause = true;
1302 else
1303 mLocalExternalDisplayPause = false;
1304#endif
1305}
1306
1307int ExynosExternalDisplay::getCecPaddr()
1308{
1309 if (!mHwc->hdmi_hpd)
1310 return -1;
1311
1312 int cecPaddr = -1;;
1313
1314 if (exynos_v4l2_g_ctrl(mMixerLayers[0].fd, V4L2_CID_TV_SOURCE_PHY_ADDR, &cecPaddr) < 0)
1315 return -1;
1316
1317 return cecPaddr;
1318}
1319
1320int ExynosExternalDisplay::blank()
1321{
1322/* USE_HDMI_BLANK */
1323 /*
1324 * V4L2_CID_TV_BLANK becomes effective
1325 * only if it is called before disable() : STREAMOFF
1326 */
1327 if (exynos_v4l2_s_ctrl(mMixerLayers[mUiIndex].fd, V4L2_CID_TV_BLANK, 1) < 0) {
1328 ALOGE("%s: s_ctrl(CID_TV_BLANK) failed %d", __func__, errno);
1329 return -1;
1330 }
1331 return 0;
1332}
1333
1334int ExynosExternalDisplay::waitForRenderFinish(private_module_t *grallocModule, buffer_handle_t *handle, int buffers)
1335{
1336 return 0;
1337}