hwc.cpp revision 46a07295367fbfcaa485e71125d41f947c9be39b
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include <errno.h>
17#include <fcntl.h>
18#include <math.h>
19#include <poll.h>
20#include <pthread.h>
21#include <stdio.h>
22#include <stdlib.h>
23
24#include <sys/ioctl.h>
25#include <sys/mman.h>
26#include <sys/time.h>
27#include <sys/resource.h>
28
29#include <s3c-fb.h>
30
31#include <EGL/egl.h>
32
33#define HWC_REMOVE_DEPRECATED_VERSIONS 1
34
35#include <cutils/compiler.h>
36#include <cutils/log.h>
37#include <cutils/properties.h>
38#include <hardware/gralloc.h>
39#include <hardware/hardware.h>
40#include <hardware/hwcomposer.h>
41#include <hardware_legacy/uevent.h>
42#include <utils/String8.h>
43#include <utils/Vector.h>
44
45#include <sync/sync.h>
46
47#include "ion.h"
48#include "gralloc_priv.h"
49#include "exynos_gscaler.h"
50#include "exynos_format.h"
51#include "exynos_v4l2.h"
52#include "s5p_tvout_v4l2.h"
53
54const size_t NUM_HW_WINDOWS = 5;
55const size_t NO_FB_NEEDED = NUM_HW_WINDOWS + 1;
56const size_t MAX_PIXELS = 2560 * 1600 * 2;
57const size_t GSC_W_ALIGNMENT = 16;
58const size_t GSC_H_ALIGNMENT = 16;
59const size_t GSC_DST_CROP_W_ALIGNMENT_RGB888 = 32;
60const size_t GSC_DST_W_ALIGNMENT_RGB888 = 32;
61const size_t GSC_DST_H_ALIGNMENT_RGB888 = 1;
62const size_t FIMD_GSC_IDX = 0;
63const size_t HDMI_GSC_IDX = 1;
64const int AVAILABLE_GSC_UNITS[] = { 0, 3 };
65const size_t NUM_GSC_UNITS = sizeof(AVAILABLE_GSC_UNITS) /
66        sizeof(AVAILABLE_GSC_UNITS[0]);
67const size_t BURSTLEN_BYTES = 16 * 8;
68const size_t NUM_HDMI_BUFFERS = 3;
69
70struct exynos5_hwc_composer_device_1_t;
71
72struct exynos5_gsc_map_t {
73    enum {
74        GSC_NONE = 0,
75        GSC_M2M,
76        // TODO: GSC_LOCAL_PATH
77    } mode;
78    int idx;
79};
80
81struct exynos5_hwc_post_data_t {
82    int                 overlay_map[NUM_HW_WINDOWS];
83    exynos5_gsc_map_t   gsc_map[NUM_HW_WINDOWS];
84    size_t              fb_window;
85};
86
87const size_t NUM_GSC_DST_BUFS = 3;
88struct exynos5_gsc_data_t {
89    void            *gsc;
90    exynos_gsc_img  src_cfg;
91    exynos_gsc_img  dst_cfg;
92    buffer_handle_t dst_buf[NUM_GSC_DST_BUFS];
93    int             dst_buf_fence[NUM_GSC_DST_BUFS];
94    size_t          current_buf;
95};
96
97struct hdmi_layer_t {
98    int     id;
99    int     fd;
100    bool    enabled;
101    exynos_gsc_img  cfg;
102
103    bool    streaming;
104    size_t  current_buf;
105    size_t  queued_buf;
106};
107
108struct exynos5_hwc_composer_device_1_t {
109    hwc_composer_device_1_t base;
110
111    int                     fd;
112    int                     vsync_fd;
113    exynos5_hwc_post_data_t bufs;
114
115    const private_module_t  *gralloc_module;
116    alloc_device_t          *alloc_device;
117    const hwc_procs_t       *procs;
118    pthread_t               vsync_thread;
119    int                     force_gpu;
120
121    int32_t                 xres;
122    int32_t                 yres;
123    int32_t                 xdpi;
124    int32_t                 ydpi;
125    int32_t                 vsync_period;
126
127    int  hdmi_mixer0;
128    bool hdmi_hpd;
129    bool hdmi_enabled;
130    bool hdmi_blanked;
131    bool hdmi_fb_needed;
132    int  hdmi_w;
133    int  hdmi_h;
134
135    hdmi_layer_t            hdmi_layers[2];
136
137    exynos5_gsc_data_t      gsc[NUM_GSC_UNITS];
138
139    struct s3c_fb_win_config last_config[NUM_HW_WINDOWS];
140    size_t                  last_fb_window;
141    const void              *last_handles[NUM_HW_WINDOWS];
142    exynos5_gsc_map_t       last_gsc_map[NUM_HW_WINDOWS];
143};
144
145static void exynos5_cleanup_gsc_m2m(exynos5_hwc_composer_device_1_t *pdev,
146        size_t gsc_idx);
147
148static void dump_handle(private_handle_t *h)
149{
150    ALOGV("\t\tformat = %d, width = %u, height = %u, stride = %u, vstride = %u",
151            h->format, h->width, h->height, h->stride, h->vstride);
152}
153
154static void dump_layer(hwc_layer_1_t const *l)
155{
156    ALOGV("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, "
157            "{%d,%d,%d,%d}, {%d,%d,%d,%d}",
158            l->compositionType, l->flags, l->handle, l->transform,
159            l->blending,
160            l->sourceCrop.left,
161            l->sourceCrop.top,
162            l->sourceCrop.right,
163            l->sourceCrop.bottom,
164            l->displayFrame.left,
165            l->displayFrame.top,
166            l->displayFrame.right,
167            l->displayFrame.bottom);
168
169    if(l->handle && !(l->flags & HWC_SKIP_LAYER))
170        dump_handle(private_handle_t::dynamicCast(l->handle));
171}
172
173static void dump_config(s3c_fb_win_config &c)
174{
175    ALOGV("\tstate = %u", c.state);
176    if (c.state == c.S3C_FB_WIN_STATE_BUFFER) {
177        ALOGV("\t\tfd = %d, offset = %u, stride = %u, "
178                "x = %d, y = %d, w = %u, h = %u, "
179                "format = %u, blending = %u",
180                c.fd, c.offset, c.stride,
181                c.x, c.y, c.w, c.h,
182                c.format, c.blending);
183    }
184    else if (c.state == c.S3C_FB_WIN_STATE_COLOR) {
185        ALOGV("\t\tcolor = %u", c.color);
186    }
187}
188
189static void dump_gsc_img(exynos_gsc_img &c)
190{
191    ALOGV("\tx = %u, y = %u, w = %u, h = %u, fw = %u, fh = %u",
192            c.x, c.y, c.w, c.h, c.fw, c.fh);
193    ALOGV("\taddr = {%u, %u, %u}, rot = %u, cacheable = %u, drmMode = %u",
194            c.yaddr, c.uaddr, c.vaddr, c.rot, c.cacheable, c.drmMode);
195}
196
197inline int WIDTH(const hwc_rect &rect) { return rect.right - rect.left; }
198inline int HEIGHT(const hwc_rect &rect) { return rect.bottom - rect.top; }
199template<typename T> inline T max(T a, T b) { return (a > b) ? a : b; }
200template<typename T> inline T min(T a, T b) { return (a < b) ? a : b; }
201
202static int dup_or_warn(int fence)
203{
204    int dup_fd = dup(fence);
205    if (dup_fd < 0)
206        ALOGW("fence dup failed: %s", strerror(errno));
207    return dup_fd;
208}
209
210static int merge_or_warn(const char *name, int f1, int f2)
211{
212    int merge_fd = sync_merge(name, f1, f2);
213    if (merge_fd < 0)
214        ALOGW("fence merge failed: %s", strerror(errno));
215    return merge_fd;
216}
217
218template<typename T> void align_crop_and_center(T &w, T &h,
219        hwc_rect_t *crop, size_t alignment)
220{
221    double aspect = 1.0 * h / w;
222    T w_orig = w, h_orig = h;
223
224    w = ALIGN(w, alignment);
225    h = round(aspect * w);
226    if (crop) {
227        crop->left = (w - w_orig) / 2;
228        crop->top = (h - h_orig) / 2;
229        crop->right = crop->left + w_orig;
230        crop->bottom = crop->top + h_orig;
231    }
232}
233
234static bool is_transformed(const hwc_layer_1_t &layer)
235{
236    return layer.transform != 0;
237}
238
239static bool is_rotated(const hwc_layer_1_t &layer)
240{
241    return (layer.transform & HAL_TRANSFORM_ROT_90) ||
242            (layer.transform & HAL_TRANSFORM_ROT_180);
243}
244
245static bool is_scaled(const hwc_layer_1_t &layer)
246{
247    return WIDTH(layer.displayFrame) != WIDTH(layer.sourceCrop) ||
248            HEIGHT(layer.displayFrame) != HEIGHT(layer.sourceCrop);
249}
250
251static inline bool gsc_dst_cfg_changed(exynos_gsc_img &c1, exynos_gsc_img &c2)
252{
253    return c1.x != c2.x ||
254            c1.y != c2.y ||
255            c1.w != c2.w ||
256            c1.h != c2.h ||
257            c1.format != c2.format ||
258            c1.rot != c2.rot ||
259            c1.cacheable != c2.cacheable ||
260            c1.drmMode != c2.drmMode;
261}
262
263static inline bool gsc_src_cfg_changed(exynos_gsc_img &c1, exynos_gsc_img &c2)
264{
265    return gsc_dst_cfg_changed(c1, c2) ||
266            c1.fw != c2.fw ||
267            c1.fh != c2.fh;
268}
269
270static enum s3c_fb_pixel_format exynos5_format_to_s3c_format(int format)
271{
272    switch (format) {
273    case HAL_PIXEL_FORMAT_RGBA_8888:
274        return S3C_FB_PIXEL_FORMAT_RGBA_8888;
275    case HAL_PIXEL_FORMAT_RGBX_8888:
276        return S3C_FB_PIXEL_FORMAT_RGBX_8888;
277    case HAL_PIXEL_FORMAT_RGBA_5551:
278        return S3C_FB_PIXEL_FORMAT_RGBA_5551;
279    case HAL_PIXEL_FORMAT_RGB_565:
280        return S3C_FB_PIXEL_FORMAT_RGB_565;
281    case HAL_PIXEL_FORMAT_BGRA_8888:
282        return S3C_FB_PIXEL_FORMAT_BGRA_8888;
283    default:
284        return S3C_FB_PIXEL_FORMAT_MAX;
285    }
286}
287
288static bool exynos5_format_is_supported(int format)
289{
290    return exynos5_format_to_s3c_format(format) < S3C_FB_PIXEL_FORMAT_MAX;
291}
292
293static bool exynos5_format_is_rgb(int format)
294{
295    switch (format) {
296    case HAL_PIXEL_FORMAT_RGBA_8888:
297    case HAL_PIXEL_FORMAT_RGBX_8888:
298    case HAL_PIXEL_FORMAT_RGB_888:
299    case HAL_PIXEL_FORMAT_RGB_565:
300    case HAL_PIXEL_FORMAT_BGRA_8888:
301    case HAL_PIXEL_FORMAT_RGBA_5551:
302    case HAL_PIXEL_FORMAT_RGBA_4444:
303        return true;
304
305    default:
306        return false;
307    }
308}
309
310static bool exynos5_format_is_supported_by_gscaler(int format)
311{
312    switch (format) {
313    case HAL_PIXEL_FORMAT_RGBX_8888:
314    case HAL_PIXEL_FORMAT_RGB_565:
315    case HAL_PIXEL_FORMAT_EXYNOS_YV12:
316    case HAL_PIXEL_FORMAT_YCbCr_420_SP:
317    case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
318        return true;
319
320    default:
321        return false;
322    }
323}
324
325static bool exynos5_format_is_ycrcb(int format)
326{
327    return format == HAL_PIXEL_FORMAT_EXYNOS_YV12;
328}
329
330static bool exynos5_format_requires_gscaler(int format)
331{
332    return (exynos5_format_is_supported_by_gscaler(format) &&
333           (format != HAL_PIXEL_FORMAT_RGBX_8888) && (format != HAL_PIXEL_FORMAT_RGB_565));
334}
335
336static uint8_t exynos5_format_to_bpp(int format)
337{
338    switch (format) {
339    case HAL_PIXEL_FORMAT_RGBA_8888:
340    case HAL_PIXEL_FORMAT_RGBX_8888:
341    case HAL_PIXEL_FORMAT_BGRA_8888:
342        return 32;
343
344    case HAL_PIXEL_FORMAT_RGBA_5551:
345    case HAL_PIXEL_FORMAT_RGBA_4444:
346    case HAL_PIXEL_FORMAT_RGB_565:
347        return 16;
348
349    default:
350        ALOGW("unrecognized pixel format %u", format);
351        return 0;
352    }
353}
354
355static bool is_x_aligned(const hwc_layer_1_t &layer, int format)
356{
357    if (!exynos5_format_is_supported(format))
358        return true;
359
360    uint8_t bpp = exynos5_format_to_bpp(format);
361    uint8_t pixel_alignment = 32 / bpp;
362
363    return (layer.displayFrame.left % pixel_alignment) == 0 &&
364            (layer.displayFrame.right % pixel_alignment) == 0;
365}
366
367static bool dst_crop_w_aligned(int dest_w)
368{
369    int dst_crop_w_alignement;
370
371   /* GSC's dst crop size should be aligned 128Bytes */
372    dst_crop_w_alignement = GSC_DST_CROP_W_ALIGNMENT_RGB888;
373
374    return (dest_w % dst_crop_w_alignement) == 0;
375}
376
377static bool exynos5_supports_gscaler(hwc_layer_1_t &layer, int format,
378        bool local_path)
379{
380    private_handle_t *handle = private_handle_t::dynamicCast(layer.handle);
381
382    int max_w = is_rotated(layer) ? 2048 : 4800;
383    int max_h = is_rotated(layer) ? 2048 : 3344;
384
385    bool rot90or270 = !!(layer.transform & HAL_TRANSFORM_ROT_90);
386    // n.b.: HAL_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_90 |
387    //                               HAL_TRANSFORM_ROT_180
388
389    int src_w = WIDTH(layer.sourceCrop), src_h = HEIGHT(layer.sourceCrop);
390    int dest_w, dest_h;
391    if (rot90or270) {
392        dest_w = HEIGHT(layer.displayFrame);
393        dest_h = WIDTH(layer.displayFrame);
394    } else {
395        dest_w = WIDTH(layer.displayFrame);
396        dest_h = HEIGHT(layer.displayFrame);
397    }
398
399    if (handle->flags & GRALLOC_USAGE_PROTECTED)
400        align_crop_and_center(dest_w, dest_h, NULL,
401                GSC_DST_CROP_W_ALIGNMENT_RGB888);
402
403    int max_downscale = local_path ? 4 : 16;
404    const int max_upscale = 8;
405
406    return exynos5_format_is_supported_by_gscaler(format) &&
407            dst_crop_w_aligned(dest_w) &&
408            handle->stride <= max_w &&
409            handle->stride % GSC_W_ALIGNMENT == 0 &&
410            src_w <= dest_w * max_downscale &&
411            dest_w <= src_w * max_upscale &&
412            handle->vstride <= max_h &&
413            handle->vstride % GSC_H_ALIGNMENT == 0 &&
414            src_h <= dest_h * max_downscale &&
415            dest_h <= src_h * max_upscale &&
416            // per 46.2
417            (!rot90or270 || layer.sourceCrop.top % 2 == 0) &&
418            (!rot90or270 || layer.sourceCrop.left % 2 == 0);
419            // per 46.3.1.6
420}
421
422static bool exynos5_requires_gscaler(hwc_layer_1_t &layer, int format)
423{
424    return exynos5_format_requires_gscaler(format) || is_scaled(layer)
425            || is_transformed(layer) || !is_x_aligned(layer, format);
426}
427
428int hdmi_get_config(struct exynos5_hwc_composer_device_1_t *dev)
429{
430    struct v4l2_dv_preset preset;
431    struct v4l2_dv_enum_preset enum_preset;
432    int index = 0;
433    bool found = false;
434    int ret;
435
436    if (ioctl(dev->hdmi_layers[0].fd, VIDIOC_G_DV_PRESET, &preset) < 0) {
437        ALOGE("%s: g_dv_preset error, %d", __func__, errno);
438        return -1;
439    }
440
441    while (true) {
442        enum_preset.index = index++;
443        ret = ioctl(dev->hdmi_layers[0].fd, VIDIOC_ENUM_DV_PRESETS, &enum_preset);
444
445        if (ret < 0) {
446            if (errno == EINVAL)
447                break;
448            ALOGE("%s: enum_dv_presets error, %d", __func__, errno);
449            return -1;
450        }
451
452        ALOGV("%s: %d preset=%02d width=%d height=%d name=%s",
453                __func__, enum_preset.index, enum_preset.preset,
454                enum_preset.width, enum_preset.height, enum_preset.name);
455
456        if (preset.preset == enum_preset.preset) {
457            dev->hdmi_w  = enum_preset.width;
458            dev->hdmi_h  = enum_preset.height;
459            found = true;
460        }
461    }
462
463    return found ? 0 : -1;
464}
465
466static enum s3c_fb_blending exynos5_blending_to_s3c_blending(int32_t blending)
467{
468    switch (blending) {
469    case HWC_BLENDING_NONE:
470        return S3C_FB_BLENDING_NONE;
471    case HWC_BLENDING_PREMULT:
472        return S3C_FB_BLENDING_PREMULT;
473    case HWC_BLENDING_COVERAGE:
474        return S3C_FB_BLENDING_COVERAGE;
475
476    default:
477        return S3C_FB_BLENDING_MAX;
478    }
479}
480
481static bool exynos5_blending_is_supported(int32_t blending)
482{
483    return exynos5_blending_to_s3c_blending(blending) < S3C_FB_BLENDING_MAX;
484}
485
486
487static int hdmi_enable_layer(struct exynos5_hwc_composer_device_1_t *dev,
488                             hdmi_layer_t &hl)
489{
490    if (hl.enabled)
491        return 0;
492
493    struct v4l2_requestbuffers reqbuf;
494    memset(&reqbuf, 0, sizeof(reqbuf));
495    reqbuf.count  = NUM_HDMI_BUFFERS;
496    reqbuf.type   = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
497    reqbuf.memory = V4L2_MEMORY_DMABUF;
498    if (exynos_v4l2_reqbufs(hl.fd, &reqbuf) < 0) {
499        ALOGE("%s: layer%d: reqbufs failed %d", __func__, hl.id, errno);
500        return -1;
501    }
502
503    if (reqbuf.count != NUM_HDMI_BUFFERS) {
504        ALOGE("%s: layer%d: didn't get buffer", __func__, hl.id);
505        return -1;
506    }
507
508    if (hl.id == 1) {
509        if (exynos_v4l2_s_ctrl(hl.fd, V4L2_CID_TV_PIXEL_BLEND_ENABLE, 1) < 0) {
510            ALOGE("%s: layer%d: PIXEL_BLEND_ENABLE failed %d", __func__,
511                                                                hl.id, errno);
512            return -1;
513        }
514    }
515
516    ALOGV("%s: layer%d enabled", __func__, hl.id);
517    hl.enabled = true;
518    return 0;
519}
520
521static void hdmi_disable_layer(struct exynos5_hwc_composer_device_1_t *dev,
522                               hdmi_layer_t &hl)
523{
524    if (!hl.enabled)
525        return;
526
527    if (hl.streaming) {
528        if (exynos_v4l2_streamoff(hl.fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) < 0)
529            ALOGE("%s: layer%d: streamoff failed %d", __func__, hl.id, errno);
530        hl.streaming = false;
531    }
532
533    struct v4l2_requestbuffers reqbuf;
534    memset(&reqbuf, 0, sizeof(reqbuf));
535    reqbuf.type   = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
536    reqbuf.memory = V4L2_MEMORY_DMABUF;
537    if (exynos_v4l2_reqbufs(hl.fd, &reqbuf) < 0)
538        ALOGE("%s: layer%d: reqbufs failed %d", __func__, hl.id, errno);
539
540    memset(&hl.cfg, 0, sizeof(hl.cfg));
541    hl.current_buf = 0;
542    hl.queued_buf = 0;
543    hl.enabled = false;
544
545    ALOGV("%s: layer%d disabled", __func__, hl.id);
546}
547
548static void hdmi_hide_layer(struct exynos5_hwc_composer_device_1_t *dev,
549                            hdmi_layer_t &hl)
550{
551    if (exynos_v4l2_s_ctrl(hl.fd, V4L2_CID_TV_LAYER_PRIO, 0) < 0)
552        ALOGE("%s: layer%d: LAYER_PRIO failed %d", __func__,
553                                                   hl.id, errno);
554}
555
556static void hdmi_show_layer(struct exynos5_hwc_composer_device_1_t *dev,
557                            hdmi_layer_t &hl)
558{
559    int prio = hl.id ? 3 : 2;
560
561    if (exynos_v4l2_s_ctrl(hl.fd, V4L2_CID_TV_LAYER_PRIO, prio) < 0)
562        ALOGE("%s: layer%d: LAYER_PRIO failed %d", __func__,
563                                                   hl.id, errno);
564}
565
566static int hdmi_enable(struct exynos5_hwc_composer_device_1_t *dev)
567{
568    /* hdmi not supported */
569    if (dev->hdmi_mixer0 < 0)
570        return 0;
571
572    if (dev->hdmi_enabled)
573        return 0;
574
575    if (dev->hdmi_blanked)
576        return 0;
577
578    struct v4l2_subdev_format sd_fmt;
579    memset(&sd_fmt, 0, sizeof(sd_fmt));
580    sd_fmt.pad   = MIXER_G0_SUBDEV_PAD_SINK;
581    sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
582    sd_fmt.format.width  = dev->hdmi_w;
583    sd_fmt.format.height = dev->hdmi_h;
584    sd_fmt.format.code   = V4L2_MBUS_FMT_XRGB8888_4X8_LE;
585    if (exynos_subdev_s_fmt(dev->hdmi_mixer0, &sd_fmt) < 0) {
586        ALOGE("%s: s_fmt failed pad=%d", __func__, sd_fmt.pad);
587        return -1;
588    }
589
590    struct v4l2_subdev_crop sd_crop;
591    memset(&sd_crop, 0, sizeof(sd_crop));
592    sd_crop.pad   = MIXER_G0_SUBDEV_PAD_SINK;
593    sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
594    sd_crop.rect.width  = dev->hdmi_w;
595    sd_crop.rect.height = dev->hdmi_h;
596    if (exynos_subdev_s_crop(dev->hdmi_mixer0, &sd_crop) < 0) {
597        ALOGE("%s: s_crop failed pad=%d", __func__, sd_crop.pad);
598        return -1;
599    }
600
601    memset(&sd_fmt, 0, sizeof(sd_fmt));
602    sd_fmt.pad   = MIXER_G0_SUBDEV_PAD_SOURCE;
603    sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
604    sd_fmt.format.width  = dev->hdmi_w;
605    sd_fmt.format.height = dev->hdmi_h;
606    sd_fmt.format.code   = V4L2_MBUS_FMT_XRGB8888_4X8_LE;
607    if (exynos_subdev_s_fmt(dev->hdmi_mixer0, &sd_fmt) < 0) {
608        ALOGE("%s: s_fmt failed pad=%d", __func__, sd_fmt.pad);
609        return -1;
610    }
611
612    memset(&sd_crop, 0, sizeof(sd_crop));
613    sd_crop.pad   = MIXER_G0_SUBDEV_PAD_SOURCE;
614    sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
615    sd_crop.rect.width  = dev->hdmi_w;
616    sd_crop.rect.height = dev->hdmi_h;
617    if (exynos_subdev_s_crop(dev->hdmi_mixer0, &sd_crop) < 0) {
618        ALOGE("%s: s_crop failed pad=%d", __func__, sd_crop.pad);
619        return -1;
620    }
621
622    char value[PROPERTY_VALUE_MAX];
623    property_get("persist.hdmi.hdcp_enabled", value, "1");
624    int hdcp_enabled = atoi(value);
625
626    if (exynos_v4l2_s_ctrl(dev->hdmi_layers[1].fd, V4L2_CID_TV_HDCP_ENABLE,
627                           hdcp_enabled) < 0)
628        ALOGE("%s: s_ctrl(CID_TV_HDCP_ENABLE) failed %d", __func__, errno);
629
630    /* "3" is RGB709_16_235 */
631    property_get("persist.hdmi.color_range", value, "3");
632    int color_range = atoi(value);
633
634    if (exynos_v4l2_s_ctrl(dev->hdmi_layers[1].fd, V4L2_CID_TV_SET_COLOR_RANGE,
635                           color_range) < 0)
636        ALOGE("%s: s_ctrl(CID_TV_COLOR_RANGE) failed %d", __func__, errno);
637
638    hdmi_enable_layer(dev, dev->hdmi_layers[1]);
639
640    dev->hdmi_enabled = true;
641    return 0;
642}
643
644static void hdmi_disable(struct exynos5_hwc_composer_device_1_t *dev)
645{
646    if (!dev->hdmi_enabled)
647        return;
648
649    hdmi_disable_layer(dev, dev->hdmi_layers[0]);
650    hdmi_disable_layer(dev, dev->hdmi_layers[1]);
651
652    exynos5_cleanup_gsc_m2m(dev, HDMI_GSC_IDX);
653    dev->hdmi_enabled = false;
654}
655
656static int hdmi_output(struct exynos5_hwc_composer_device_1_t *dev,
657                       hdmi_layer_t &hl,
658                       hwc_layer_1_t &layer,
659                       private_handle_t *h,
660                       int acquireFenceFd,
661                       int *releaseFenceFd)
662{
663    int ret = 0;
664
665    exynos_gsc_img cfg;
666    memset(&cfg, 0, sizeof(cfg));
667    cfg.x = layer.displayFrame.left;
668    cfg.y = layer.displayFrame.top;
669    cfg.w = WIDTH(layer.displayFrame);
670    cfg.h = HEIGHT(layer.displayFrame);
671
672    if (gsc_src_cfg_changed(hl.cfg, cfg)) {
673        hdmi_disable_layer(dev, hl);
674
675        struct v4l2_format fmt;
676        memset(&fmt, 0, sizeof(fmt));
677        fmt.type  = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
678        fmt.fmt.pix_mp.width       = h->stride;
679        fmt.fmt.pix_mp.height      = cfg.h;
680        fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_BGR32;
681        fmt.fmt.pix_mp.field       = V4L2_FIELD_ANY;
682        fmt.fmt.pix_mp.num_planes  = 1;
683        ret = exynos_v4l2_s_fmt(hl.fd, &fmt);
684        if (ret < 0) {
685            ALOGE("%s: layer%d: s_fmt failed %d", __func__, hl.id, errno);
686            goto err;
687        }
688
689        struct v4l2_subdev_crop sd_crop;
690        memset(&sd_crop, 0, sizeof(sd_crop));
691        if (hl.id == 0)
692            sd_crop.pad   = MIXER_G0_SUBDEV_PAD_SOURCE;
693        else
694            sd_crop.pad   = MIXER_G1_SUBDEV_PAD_SOURCE;
695        sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
696        sd_crop.rect.left   = cfg.x;
697        sd_crop.rect.top    = cfg.y;
698        sd_crop.rect.width  = cfg.w;
699        sd_crop.rect.height = cfg.h;
700        if (exynos_subdev_s_crop(dev->hdmi_mixer0, &sd_crop) < 0) {
701            ALOGE("%s: s_crop failed pad=%d", __func__, sd_crop.pad);
702            goto err;
703        }
704
705        hdmi_enable_layer(dev, hl);
706
707        ALOGV("HDMI layer%d configuration:", hl.id);
708        dump_gsc_img(cfg);
709        hl.cfg = cfg;
710    }
711
712    struct v4l2_buffer buffer;
713    struct v4l2_plane planes[1];
714
715    if (hl.queued_buf == NUM_HDMI_BUFFERS) {
716        memset(&buffer, 0, sizeof(buffer));
717        memset(planes, 0, sizeof(planes));
718        buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
719        buffer.memory = V4L2_MEMORY_DMABUF;
720        buffer.length = 1;
721        buffer.m.planes = planes;
722        ret = exynos_v4l2_dqbuf(hl.fd, &buffer);
723        if (ret < 0) {
724            ALOGE("%s: layer%d: dqbuf failed %d", __func__, hl.id, errno);
725            goto err;
726        }
727        hl.queued_buf--;
728    }
729
730    memset(&buffer, 0, sizeof(buffer));
731    memset(planes, 0, sizeof(planes));
732    buffer.index = hl.current_buf;
733    buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
734    buffer.memory = V4L2_MEMORY_DMABUF;
735    buffer.flags = V4L2_BUF_FLAG_USE_SYNC;
736    buffer.reserved = acquireFenceFd;
737    buffer.length = 1;
738    buffer.m.planes = planes;
739    buffer.m.planes[0].m.fd = h->fd;
740    if (exynos_v4l2_qbuf(hl.fd, &buffer) < 0) {
741        ALOGE("%s: layer%d: qbuf failed %d", __func__, hl.id, errno);
742        ret = -1;
743        goto err;
744    }
745
746    if (releaseFenceFd)
747        *releaseFenceFd = buffer.reserved;
748    else
749        close(buffer.reserved);
750
751    hl.queued_buf++;
752    hl.current_buf = (hl.current_buf + 1) % NUM_HDMI_BUFFERS;
753
754    if (!hl.streaming) {
755        if (exynos_v4l2_streamon(hl.fd, buffer.type) < 0) {
756            ALOGE("%s: layer%d: streamon failed %d", __func__, hl.id, errno);
757            ret = -1;
758            goto err;
759        }
760        hl.streaming = true;
761    }
762
763err:
764    if (acquireFenceFd >= 0)
765        close(acquireFenceFd);
766
767    return ret;
768}
769
770bool exynos5_is_offscreen(hwc_layer_1_t &layer,
771        struct exynos5_hwc_composer_device_1_t *pdev)
772{
773    return layer.sourceCrop.left > pdev->xres ||
774            layer.sourceCrop.right < 0 ||
775            layer.sourceCrop.top > pdev->yres ||
776            layer.sourceCrop.bottom < 0;
777}
778
779size_t exynos5_visible_width(hwc_layer_1_t &layer, int format,
780        struct exynos5_hwc_composer_device_1_t *pdev)
781{
782    int bpp;
783    if (exynos5_requires_gscaler(layer, format))
784        bpp = 32;
785    else
786        bpp = exynos5_format_to_bpp(format);
787    int left = max(layer.displayFrame.left, 0);
788    int right = min(layer.displayFrame.right, pdev->xres);
789
790    return (right - left) * bpp / 8;
791}
792
793bool exynos5_supports_overlay(hwc_layer_1_t &layer, size_t i,
794        struct exynos5_hwc_composer_device_1_t *pdev)
795{
796    if (layer.flags & HWC_SKIP_LAYER) {
797        ALOGV("\tlayer %u: skipping", i);
798        return false;
799    }
800
801    private_handle_t *handle = private_handle_t::dynamicCast(layer.handle);
802
803    if (!handle) {
804        ALOGV("\tlayer %u: handle is NULL", i);
805        return false;
806    }
807
808    if (exynos5_visible_width(layer, handle->format, pdev) < BURSTLEN_BYTES) {
809        ALOGV("\tlayer %u: visible area is too narrow", i);
810        return false;
811    }
812    if (exynos5_requires_gscaler(layer, handle->format)) {
813        if (!exynos5_supports_gscaler(layer, handle->format, false)) {
814            ALOGV("\tlayer %u: gscaler required but not supported", i);
815            return false;
816        }
817    } else {
818        if (!exynos5_format_is_supported(handle->format)) {
819            ALOGV("\tlayer %u: pixel format %u not supported", i, handle->format);
820            return false;
821        }
822    }
823    if (!exynos5_blending_is_supported(layer.blending)) {
824        ALOGV("\tlayer %u: blending %d not supported", i, layer.blending);
825        return false;
826    }
827    if (CC_UNLIKELY(exynos5_is_offscreen(layer, pdev))) {
828        ALOGW("\tlayer %u: off-screen", i);
829        return false;
830    }
831
832    return true;
833}
834
835inline bool intersect(const hwc_rect &r1, const hwc_rect &r2)
836{
837    return !(r1.left > r2.right ||
838        r1.right < r2.left ||
839        r1.top > r2.bottom ||
840        r1.bottom < r2.top);
841}
842
843inline hwc_rect intersection(const hwc_rect &r1, const hwc_rect &r2)
844{
845    hwc_rect i;
846    i.top = max(r1.top, r2.top);
847    i.bottom = min(r1.bottom, r2.bottom);
848    i.left = max(r1.left, r2.left);
849    i.right = min(r1.right, r2.right);
850    return i;
851}
852
853static int exynos5_prepare_fimd(exynos5_hwc_composer_device_1_t *pdev,
854        hwc_display_contents_1_t* contents)
855{
856    ALOGV("preparing %u layers for FIMD", contents->numHwLayers);
857
858    memset(pdev->bufs.gsc_map, 0, sizeof(pdev->bufs.gsc_map));
859
860    bool force_fb = pdev->force_gpu;
861    for (size_t i = 0; i < NUM_HW_WINDOWS; i++)
862        pdev->bufs.overlay_map[i] = -1;
863
864    bool fb_needed = false;
865    size_t first_fb = 0, last_fb = 0;
866
867    // find unsupported overlays
868    for (size_t i = 0; i < contents->numHwLayers; i++) {
869        hwc_layer_1_t &layer = contents->hwLayers[i];
870
871        if (layer.compositionType == HWC_FRAMEBUFFER_TARGET) {
872            ALOGV("\tlayer %u: framebuffer target", i);
873            continue;
874        }
875
876        if (layer.compositionType == HWC_BACKGROUND && !force_fb) {
877            ALOGV("\tlayer %u: background supported", i);
878            dump_layer(&contents->hwLayers[i]);
879            continue;
880        }
881
882        if (exynos5_supports_overlay(contents->hwLayers[i], i, pdev) &&
883                !force_fb) {
884            ALOGV("\tlayer %u: overlay supported", i);
885            layer.compositionType = HWC_OVERLAY;
886            dump_layer(&contents->hwLayers[i]);
887            continue;
888        }
889
890        if (!fb_needed) {
891            first_fb = i;
892            fb_needed = true;
893        }
894        last_fb = i;
895        layer.compositionType = HWC_FRAMEBUFFER;
896
897        dump_layer(&contents->hwLayers[i]);
898    }
899
900    // can't composite overlays sandwiched between framebuffers
901    if (fb_needed)
902        for (size_t i = first_fb; i < last_fb; i++)
903            contents->hwLayers[i].compositionType = HWC_FRAMEBUFFER;
904
905    // Incrementally try to add our supported layers to hardware windows.
906    // If adding a layer would violate a hardware constraint, force it
907    // into the framebuffer and try again.  (Revisiting the entire list is
908    // necessary because adding a layer to the framebuffer can cause other
909    // windows to retroactively violate constraints.)
910    bool changed;
911    bool gsc_used;
912    do {
913        android::Vector<hwc_rect> rects;
914        android::Vector<hwc_rect> overlaps;
915        size_t pixels_left, windows_left;
916
917        gsc_used = false;
918
919        if (fb_needed) {
920            hwc_rect_t fb_rect;
921            fb_rect.top = fb_rect.left = 0;
922            fb_rect.right = pdev->xres - 1;
923            fb_rect.bottom = pdev->yres - 1;
924            pixels_left = MAX_PIXELS - pdev->xres * pdev->yres;
925            windows_left = NUM_HW_WINDOWS - 1;
926            rects.push_back(fb_rect);
927        }
928        else {
929            pixels_left = MAX_PIXELS;
930            windows_left = NUM_HW_WINDOWS;
931        }
932
933        changed = false;
934
935        for (size_t i = 0; i < contents->numHwLayers; i++) {
936            hwc_layer_1_t &layer = contents->hwLayers[i];
937            if ((layer.flags & HWC_SKIP_LAYER) ||
938                    layer.compositionType == HWC_FRAMEBUFFER_TARGET)
939                continue;
940
941            private_handle_t *handle = private_handle_t::dynamicCast(
942                    layer.handle);
943
944            // we've already accounted for the framebuffer above
945            if (layer.compositionType == HWC_FRAMEBUFFER)
946                continue;
947
948            // only layer 0 can be HWC_BACKGROUND, so we can
949            // unconditionally allow it without extra checks
950            if (layer.compositionType == HWC_BACKGROUND) {
951                windows_left--;
952                continue;
953            }
954
955            size_t pixels_needed = WIDTH(layer.displayFrame) *
956                    HEIGHT(layer.displayFrame);
957            bool can_compose = windows_left && pixels_needed <= pixels_left;
958            bool gsc_required = exynos5_requires_gscaler(layer, handle->format);
959            if (gsc_required)
960                can_compose = can_compose && !gsc_used;
961
962            // hwc_rect_t right and bottom values are normally exclusive;
963            // the intersection logic is simpler if we make them inclusive
964            hwc_rect_t visible_rect = layer.displayFrame;
965            visible_rect.right--; visible_rect.bottom--;
966
967            // no more than 2 layers can overlap on a given pixel
968            for (size_t j = 0; can_compose && j < overlaps.size(); j++) {
969                if (intersect(visible_rect, overlaps.itemAt(j)))
970                    can_compose = false;
971            }
972
973            if (!can_compose) {
974                layer.compositionType = HWC_FRAMEBUFFER;
975                if (!fb_needed) {
976                    first_fb = last_fb = i;
977                    fb_needed = true;
978                }
979                else {
980                    first_fb = min(i, first_fb);
981                    last_fb = max(i, last_fb);
982                }
983                changed = true;
984                break;
985            }
986
987            for (size_t j = 0; j < rects.size(); j++) {
988                const hwc_rect_t &other_rect = rects.itemAt(j);
989                if (intersect(visible_rect, other_rect))
990                    overlaps.push_back(intersection(visible_rect, other_rect));
991            }
992            rects.push_back(visible_rect);
993            pixels_left -= pixels_needed;
994            windows_left--;
995            if (gsc_required)
996                gsc_used = true;
997        }
998
999        if (changed)
1000            for (size_t i = first_fb; i < last_fb; i++)
1001                contents->hwLayers[i].compositionType = HWC_FRAMEBUFFER;
1002    } while(changed);
1003
1004    unsigned int nextWindow = 0;
1005
1006    for (size_t i = 0; i < contents->numHwLayers; i++) {
1007        hwc_layer_1_t &layer = contents->hwLayers[i];
1008
1009        if (fb_needed && i == first_fb) {
1010            ALOGV("assigning framebuffer to window %u\n",
1011                    nextWindow);
1012            nextWindow++;
1013            continue;
1014        }
1015
1016        if (layer.compositionType != HWC_FRAMEBUFFER &&
1017                layer.compositionType != HWC_FRAMEBUFFER_TARGET) {
1018            ALOGV("assigning layer %u to window %u", i, nextWindow);
1019            pdev->bufs.overlay_map[nextWindow] = i;
1020            if (layer.compositionType == HWC_OVERLAY) {
1021                private_handle_t *handle =
1022                        private_handle_t::dynamicCast(layer.handle);
1023                if (exynos5_requires_gscaler(layer, handle->format)) {
1024                    ALOGV("\tusing gscaler %u", AVAILABLE_GSC_UNITS[FIMD_GSC_IDX]);
1025                    pdev->bufs.gsc_map[nextWindow].mode =
1026                            exynos5_gsc_map_t::GSC_M2M;
1027                    pdev->bufs.gsc_map[nextWindow].idx = FIMD_GSC_IDX;
1028                }
1029            }
1030            nextWindow++;
1031        }
1032    }
1033
1034    if (!gsc_used)
1035        exynos5_cleanup_gsc_m2m(pdev, FIMD_GSC_IDX);
1036
1037    if (fb_needed)
1038        pdev->bufs.fb_window = first_fb;
1039    else
1040        pdev->bufs.fb_window = NO_FB_NEEDED;
1041
1042    return 0;
1043}
1044
1045static int exynos5_prepare_hdmi(exynos5_hwc_composer_device_1_t *pdev,
1046        hwc_display_contents_1_t* contents)
1047{
1048    ALOGV("preparing %u layers for HDMI", contents->numHwLayers);
1049    hwc_layer_1_t *video_layer = NULL;
1050
1051    pdev->hdmi_fb_needed = false;
1052
1053    for (size_t i = 0; i < contents->numHwLayers; i++) {
1054        hwc_layer_1_t &layer = contents->hwLayers[i];
1055
1056        if (layer.compositionType == HWC_FRAMEBUFFER_TARGET) {
1057            ALOGV("\tlayer %u: framebuffer target", i);
1058            continue;
1059        }
1060
1061        if (layer.compositionType == HWC_BACKGROUND) {
1062            ALOGV("\tlayer %u: background layer", i);
1063            dump_layer(&layer);
1064            continue;
1065        }
1066
1067        if (layer.handle) {
1068            private_handle_t *h = private_handle_t::dynamicCast(layer.handle);
1069            if (h->flags & GRALLOC_USAGE_PROTECTED) {
1070                if (!video_layer) {
1071                    video_layer = &layer;
1072                    layer.compositionType = HWC_OVERLAY;
1073                    ALOGV("\tlayer %u: video layer", i);
1074                    dump_layer(&layer);
1075                    continue;
1076                }
1077            }
1078        }
1079
1080        pdev->hdmi_fb_needed = true;
1081        layer.compositionType = HWC_FRAMEBUFFER;
1082        dump_layer(&layer);
1083    }
1084
1085    return 0;
1086}
1087
1088static int exynos5_prepare(hwc_composer_device_1_t *dev,
1089        size_t numDisplays, hwc_display_contents_1_t** displays)
1090{
1091    if (!numDisplays || !displays)
1092        return 0;
1093
1094    exynos5_hwc_composer_device_1_t *pdev =
1095            (exynos5_hwc_composer_device_1_t *)dev;
1096    hwc_display_contents_1_t *fimd_contents = displays[HWC_DISPLAY_PRIMARY];
1097    hwc_display_contents_1_t *hdmi_contents = displays[HWC_DISPLAY_EXTERNAL];
1098
1099    if (pdev->hdmi_hpd) {
1100        hdmi_enable(pdev);
1101    } else {
1102        hdmi_disable(pdev);
1103    }
1104
1105    if (fimd_contents) {
1106        int err = exynos5_prepare_fimd(pdev, fimd_contents);
1107        if (err)
1108            return err;
1109    }
1110
1111    if (hdmi_contents) {
1112        int err = exynos5_prepare_hdmi(pdev, hdmi_contents);
1113        if (err)
1114            return err;
1115    }
1116
1117    return 0;
1118}
1119
1120static int exynos5_config_gsc_m2m(hwc_layer_1_t &layer,
1121        alloc_device_t* alloc_device, exynos5_gsc_data_t *gsc_data,
1122        int gsc_idx, int dst_format, hwc_rect_t *sourceCrop)
1123{
1124    ALOGV("configuring gscaler %u for memory-to-memory", AVAILABLE_GSC_UNITS[gsc_idx]);
1125
1126    private_handle_t *src_handle = private_handle_t::dynamicCast(layer.handle);
1127    buffer_handle_t dst_buf;
1128    private_handle_t *dst_handle;
1129    int ret = 0;
1130
1131    exynos_gsc_img src_cfg, dst_cfg;
1132    memset(&src_cfg, 0, sizeof(src_cfg));
1133    memset(&dst_cfg, 0, sizeof(dst_cfg));
1134
1135    hwc_rect_t sourceCropTemp;
1136    if (!sourceCrop)
1137        sourceCrop = &sourceCropTemp;
1138
1139    src_cfg.x = layer.sourceCrop.left;
1140    src_cfg.y = layer.sourceCrop.top;
1141    src_cfg.w = WIDTH(layer.sourceCrop);
1142    src_cfg.fw = src_handle->stride;
1143    src_cfg.h = HEIGHT(layer.sourceCrop);
1144    src_cfg.fh = src_handle->vstride;
1145    src_cfg.yaddr = src_handle->fd;
1146    if (exynos5_format_is_ycrcb(src_handle->format)) {
1147        src_cfg.uaddr = src_handle->fd2;
1148        src_cfg.vaddr = src_handle->fd1;
1149    } else {
1150        src_cfg.uaddr = src_handle->fd1;
1151        src_cfg.vaddr = src_handle->fd2;
1152    }
1153    src_cfg.format = src_handle->format;
1154    src_cfg.drmMode = !!(src_handle->flags & GRALLOC_USAGE_PROTECTED);
1155    src_cfg.acquireFenceFd = layer.acquireFenceFd;
1156    layer.acquireFenceFd = -1;
1157
1158    dst_cfg.x = 0;
1159    dst_cfg.y = 0;
1160    dst_cfg.w = WIDTH(layer.displayFrame);
1161    dst_cfg.h = HEIGHT(layer.displayFrame);
1162    dst_cfg.rot = layer.transform;
1163    dst_cfg.drmMode = src_cfg.drmMode;
1164    dst_cfg.format = dst_format;
1165    dst_cfg.narrowRgb = !exynos5_format_is_rgb(src_handle->format);
1166    if (dst_cfg.drmMode)
1167        align_crop_and_center(dst_cfg.w, dst_cfg.h, sourceCrop,
1168                GSC_DST_CROP_W_ALIGNMENT_RGB888);
1169
1170    ALOGV("source configuration:");
1171    dump_gsc_img(src_cfg);
1172
1173    bool reconfigure = gsc_src_cfg_changed(src_cfg, gsc_data->src_cfg) ||
1174            gsc_dst_cfg_changed(dst_cfg, gsc_data->dst_cfg);
1175    if (reconfigure) {
1176        int dst_stride;
1177        int usage = GRALLOC_USAGE_SW_READ_NEVER |
1178                GRALLOC_USAGE_SW_WRITE_NEVER |
1179                GRALLOC_USAGE_HW_COMPOSER;
1180
1181        if (src_handle->flags & GRALLOC_USAGE_PROTECTED)
1182            usage |= GRALLOC_USAGE_PROTECTED;
1183
1184        int w = ALIGN(dst_cfg.w, GSC_DST_W_ALIGNMENT_RGB888);
1185        int h = ALIGN(dst_cfg.h, GSC_DST_H_ALIGNMENT_RGB888);
1186
1187        for (size_t i = 0; i < NUM_GSC_DST_BUFS; i++) {
1188            if (gsc_data->dst_buf[i]) {
1189                alloc_device->free(alloc_device, gsc_data->dst_buf[i]);
1190                gsc_data->dst_buf[i] = NULL;
1191            }
1192
1193            if (gsc_data->dst_buf_fence[i] >= 0) {
1194                close(gsc_data->dst_buf_fence[i]);
1195                gsc_data->dst_buf_fence[i] = -1;
1196            }
1197
1198            int ret = alloc_device->alloc(alloc_device, w, h,
1199                    HAL_PIXEL_FORMAT_RGBX_8888, usage, &gsc_data->dst_buf[i],
1200                    &dst_stride);
1201            if (ret < 0) {
1202                ALOGE("failed to allocate destination buffer: %s",
1203                        strerror(-ret));
1204                goto err_alloc;
1205            }
1206        }
1207
1208        gsc_data->current_buf = 0;
1209    }
1210
1211    dst_buf = gsc_data->dst_buf[gsc_data->current_buf];
1212    dst_handle = private_handle_t::dynamicCast(dst_buf);
1213
1214    dst_cfg.fw = dst_handle->stride;
1215    dst_cfg.fh = dst_handle->vstride;
1216    dst_cfg.yaddr = dst_handle->fd;
1217    dst_cfg.acquireFenceFd = gsc_data->dst_buf_fence[gsc_data->current_buf];
1218    gsc_data->dst_buf_fence[gsc_data->current_buf] = -1;
1219
1220    ALOGV("destination configuration:");
1221    dump_gsc_img(dst_cfg);
1222
1223    if ((int)dst_cfg.w != WIDTH(layer.displayFrame))
1224        ALOGV("padding %u x %u output to %u x %u and cropping to {%u,%u,%u,%u}",
1225                WIDTH(layer.displayFrame), HEIGHT(layer.displayFrame),
1226                dst_cfg.w, dst_cfg.h, sourceCrop->left, sourceCrop->top,
1227                sourceCrop->right, sourceCrop->bottom);
1228
1229    if (gsc_data->gsc) {
1230        ALOGV("reusing open gscaler %u", AVAILABLE_GSC_UNITS[gsc_idx]);
1231    } else {
1232        ALOGV("opening gscaler %u", AVAILABLE_GSC_UNITS[gsc_idx]);
1233        gsc_data->gsc = exynos_gsc_create_exclusive(
1234                AVAILABLE_GSC_UNITS[gsc_idx], GSC_M2M_MODE, GSC_DUMMY, true);
1235        if (!gsc_data->gsc) {
1236            ALOGE("failed to create gscaler handle");
1237            ret = -1;
1238            goto err_alloc;
1239        }
1240    }
1241
1242    if (reconfigure) {
1243        ret = exynos_gsc_stop_exclusive(gsc_data->gsc);
1244        if (ret < 0) {
1245            ALOGE("failed to stop gscaler %u", gsc_idx);
1246            goto err_gsc_config;
1247        }
1248
1249        ret = exynos_gsc_config_exclusive(gsc_data->gsc, &src_cfg, &dst_cfg);
1250        if (ret < 0) {
1251            ALOGE("failed to configure gscaler %u", gsc_idx);
1252            goto err_gsc_config;
1253        }
1254    }
1255
1256    ret = exynos_gsc_run_exclusive(gsc_data->gsc, &src_cfg, &dst_cfg);
1257    if (ret < 0) {
1258        ALOGE("failed to run gscaler %u", gsc_idx);
1259        goto err_gsc_config;
1260    }
1261
1262    gsc_data->src_cfg = src_cfg;
1263    gsc_data->dst_cfg = dst_cfg;
1264
1265    layer.releaseFenceFd = src_cfg.releaseFenceFd;
1266
1267    return 0;
1268
1269err_gsc_config:
1270    exynos_gsc_destroy(gsc_data->gsc);
1271    gsc_data->gsc = NULL;
1272err_alloc:
1273    if (src_cfg.acquireFenceFd >= 0)
1274        close(src_cfg.acquireFenceFd);
1275    for (size_t i = 0; i < NUM_GSC_DST_BUFS; i++) {
1276       if (gsc_data->dst_buf[i]) {
1277           alloc_device->free(alloc_device, gsc_data->dst_buf[i]);
1278           gsc_data->dst_buf[i] = NULL;
1279       }
1280       if (gsc_data->dst_buf_fence[i] >= 0) {
1281           close(gsc_data->dst_buf_fence[i]);
1282           gsc_data->dst_buf_fence[i] = -1;
1283       }
1284    }
1285    memset(&gsc_data->src_cfg, 0, sizeof(gsc_data->src_cfg));
1286    memset(&gsc_data->dst_cfg, 0, sizeof(gsc_data->dst_cfg));
1287    return ret;
1288}
1289
1290
1291static void exynos5_cleanup_gsc_m2m(exynos5_hwc_composer_device_1_t *pdev,
1292        size_t gsc_idx)
1293{
1294    exynos5_gsc_data_t &gsc_data = pdev->gsc[gsc_idx];
1295    if (!gsc_data.gsc)
1296        return;
1297
1298    ALOGV("closing gscaler %u", AVAILABLE_GSC_UNITS[gsc_idx]);
1299
1300    exynos_gsc_stop_exclusive(gsc_data.gsc);
1301    exynos_gsc_destroy(gsc_data.gsc);
1302    for (size_t i = 0; i < NUM_GSC_DST_BUFS; i++) {
1303        if (gsc_data.dst_buf[i])
1304            pdev->alloc_device->free(pdev->alloc_device, gsc_data.dst_buf[i]);
1305        if (gsc_data.dst_buf_fence[i] >= 0)
1306            close(gsc_data.dst_buf_fence[i]);
1307    }
1308
1309    memset(&gsc_data, 0, sizeof(gsc_data));
1310    for (size_t i = 0; i < NUM_GSC_DST_BUFS; i++)
1311        gsc_data.dst_buf_fence[i] = -1;
1312}
1313
1314static void exynos5_config_handle(private_handle_t *handle,
1315        hwc_rect_t &sourceCrop, hwc_rect_t &displayFrame,
1316        int32_t blending, int fence_fd, s3c_fb_win_config &cfg,
1317        exynos5_hwc_composer_device_1_t *pdev)
1318{
1319    uint32_t x, y;
1320    uint32_t w = WIDTH(displayFrame);
1321    uint32_t h = HEIGHT(displayFrame);
1322    uint8_t bpp = exynos5_format_to_bpp(handle->format);
1323    uint32_t offset = (sourceCrop.top * handle->stride + sourceCrop.left) * bpp / 8;
1324
1325    if (displayFrame.left < 0) {
1326        unsigned int crop = -displayFrame.left;
1327        ALOGV("layer off left side of screen; cropping %u pixels from left edge",
1328                crop);
1329        x = 0;
1330        w -= crop;
1331        offset += crop * bpp / 8;
1332    } else {
1333        x = displayFrame.left;
1334    }
1335
1336    if (displayFrame.right > pdev->xres) {
1337        unsigned int crop = displayFrame.right - pdev->xres;
1338        ALOGV("layer off right side of screen; cropping %u pixels from right edge",
1339                crop);
1340        w -= crop;
1341    }
1342
1343    if (displayFrame.top < 0) {
1344        unsigned int crop = -displayFrame.top;
1345        ALOGV("layer off top side of screen; cropping %u pixels from top edge",
1346                crop);
1347        y = 0;
1348        h -= crop;
1349        offset += handle->stride * crop * bpp / 8;
1350    } else {
1351        y = displayFrame.top;
1352    }
1353
1354    if (displayFrame.bottom > pdev->yres) {
1355        int crop = displayFrame.bottom - pdev->yres;
1356        ALOGV("layer off bottom side of screen; cropping %u pixels from bottom edge",
1357                crop);
1358        h -= crop;
1359    }
1360
1361    cfg.state = cfg.S3C_FB_WIN_STATE_BUFFER;
1362    cfg.fd = handle->fd;
1363    cfg.x = x;
1364    cfg.y = y;
1365    cfg.w = w;
1366    cfg.h = h;
1367    cfg.format = exynos5_format_to_s3c_format(handle->format);
1368    cfg.offset = offset;
1369    cfg.stride = handle->stride * bpp / 8;
1370    cfg.blending = exynos5_blending_to_s3c_blending(blending);
1371    cfg.fence_fd = fence_fd;
1372}
1373
1374static void exynos5_config_overlay(hwc_layer_1_t *layer, s3c_fb_win_config &cfg,
1375        exynos5_hwc_composer_device_1_t *pdev)
1376{
1377    if (layer->compositionType == HWC_BACKGROUND) {
1378        hwc_color_t color = layer->backgroundColor;
1379        cfg.state = cfg.S3C_FB_WIN_STATE_COLOR;
1380        cfg.color = (color.r << 16) | (color.g << 8) | color.b;
1381        cfg.x = 0;
1382        cfg.y = 0;
1383        cfg.w = pdev->xres;
1384        cfg.h = pdev->yres;
1385        return;
1386    }
1387
1388    private_handle_t *handle = private_handle_t::dynamicCast(layer->handle);
1389    exynos5_config_handle(handle, layer->sourceCrop, layer->displayFrame,
1390            layer->blending, layer->acquireFenceFd, cfg, pdev);
1391}
1392
1393static int exynos5_post_fimd(exynos5_hwc_composer_device_1_t *pdev,
1394        hwc_display_contents_1_t* contents)
1395{
1396    exynos5_hwc_post_data_t *pdata = &pdev->bufs;
1397    struct s3c_fb_win_config_data win_data;
1398    struct s3c_fb_win_config *config = win_data.config;
1399
1400    memset(config, 0, sizeof(win_data.config));
1401    for (size_t i = 0; i < NUM_HW_WINDOWS; i++)
1402        config[i].fence_fd = -1;
1403
1404    for (size_t i = 0; i < NUM_HW_WINDOWS; i++) {
1405        int layer_idx = pdata->overlay_map[i];
1406        if (layer_idx != -1) {
1407            hwc_layer_1_t &layer = contents->hwLayers[layer_idx];
1408            private_handle_t *handle =
1409                    private_handle_t::dynamicCast(layer.handle);
1410
1411            if (pdata->gsc_map[i].mode == exynos5_gsc_map_t::GSC_M2M) {
1412                int gsc_idx = pdata->gsc_map[i].idx;
1413                exynos5_gsc_data_t &gsc = pdev->gsc[gsc_idx];
1414
1415                // RGBX8888 surfaces are already in the right color order from the GPU,
1416                // RGB565 and YUV surfaces need the Gscaler to swap R & B
1417                int dst_format = HAL_PIXEL_FORMAT_BGRA_8888;
1418                if (exynos5_format_is_rgb(handle->format) &&
1419                                handle->format != HAL_PIXEL_FORMAT_RGB_565)
1420                    dst_format = HAL_PIXEL_FORMAT_RGBX_8888;
1421
1422                hwc_rect_t sourceCrop = { 0, 0,
1423                        WIDTH(layer.displayFrame), HEIGHT(layer.displayFrame) };
1424                int err = exynos5_config_gsc_m2m(layer, pdev->alloc_device, &gsc,
1425                        gsc_idx, dst_format, &sourceCrop);
1426                if (err < 0) {
1427                    ALOGE("failed to configure gscaler %u for layer %u",
1428                            gsc_idx, i);
1429                    pdata->gsc_map[i].mode = exynos5_gsc_map_t::GSC_NONE;
1430                    continue;
1431                }
1432
1433                buffer_handle_t dst_buf = gsc.dst_buf[gsc.current_buf];
1434                private_handle_t *dst_handle =
1435                        private_handle_t::dynamicCast(dst_buf);
1436                int fence = gsc.dst_cfg.releaseFenceFd;
1437                exynos5_config_handle(dst_handle, sourceCrop,
1438                        layer.displayFrame, layer.blending, fence, config[i],
1439                        pdev);
1440            } else {
1441                exynos5_config_overlay(&layer, config[i], pdev);
1442            }
1443        }
1444        if (i == 0 && config[i].blending != S3C_FB_BLENDING_NONE) {
1445            ALOGV("blending not supported on window 0; forcing BLENDING_NONE");
1446            config[i].blending = S3C_FB_BLENDING_NONE;
1447        }
1448
1449        ALOGV("window %u configuration:", i);
1450        dump_config(config[i]);
1451    }
1452
1453    int ret = ioctl(pdev->fd, S3CFB_WIN_CONFIG, &win_data);
1454    for (size_t i = 0; i < NUM_HW_WINDOWS; i++)
1455        if (config[i].fence_fd != -1)
1456            close(config[i].fence_fd);
1457    if (ret < 0) {
1458        ALOGE("ioctl S3CFB_WIN_CONFIG failed: %s", strerror(errno));
1459        return ret;
1460    }
1461
1462    memcpy(pdev->last_config, &win_data.config, sizeof(win_data.config));
1463    memcpy(pdev->last_gsc_map, pdata->gsc_map, sizeof(pdata->gsc_map));
1464    pdev->last_fb_window = pdata->fb_window;
1465    for (size_t i = 0; i < NUM_HW_WINDOWS; i++) {
1466        int layer_idx = pdata->overlay_map[i];
1467        if (layer_idx != -1) {
1468            hwc_layer_1_t &layer = contents->hwLayers[layer_idx];
1469            pdev->last_handles[i] = layer.handle;
1470        }
1471    }
1472
1473    return win_data.fence;
1474}
1475
1476static int exynos5_clear_fimd(exynos5_hwc_composer_device_1_t *pdev)
1477{
1478    struct s3c_fb_win_config_data win_data;
1479    memset(&win_data, 0, sizeof(win_data));
1480
1481    int ret = ioctl(pdev->fd, S3CFB_WIN_CONFIG, &win_data);
1482    LOG_ALWAYS_FATAL_IF(ret < 0,
1483            "ioctl S3CFB_WIN_CONFIG failed to clear screen: %s",
1484            strerror(errno));
1485    // the causes of an empty config failing are all unrecoverable
1486
1487    return win_data.fence;
1488}
1489
1490static int exynos5_set_fimd(exynos5_hwc_composer_device_1_t *pdev,
1491        hwc_display_contents_1_t* contents)
1492{
1493    if (!contents->dpy || !contents->sur)
1494        return 0;
1495
1496    hwc_layer_1_t *fb_layer = NULL;
1497    int err = 0;
1498
1499    if (pdev->bufs.fb_window != NO_FB_NEEDED) {
1500        for (size_t i = 0; i < contents->numHwLayers; i++) {
1501            if (contents->hwLayers[i].compositionType ==
1502                    HWC_FRAMEBUFFER_TARGET) {
1503                pdev->bufs.overlay_map[pdev->bufs.fb_window] = i;
1504                fb_layer = &contents->hwLayers[i];
1505                break;
1506            }
1507        }
1508
1509        if (CC_UNLIKELY(!fb_layer)) {
1510            ALOGE("framebuffer target expected, but not provided");
1511            err = -EINVAL;
1512        } else {
1513            ALOGV("framebuffer target buffer:");
1514            dump_layer(fb_layer);
1515        }
1516    }
1517
1518    int fence;
1519    if (!err) {
1520        fence = exynos5_post_fimd(pdev, contents);
1521        if (fence < 0)
1522            err = fence;
1523    }
1524
1525    if (err)
1526        fence = exynos5_clear_fimd(pdev);
1527
1528    for (size_t i = 0; i < NUM_HW_WINDOWS; i++) {
1529        if (pdev->bufs.overlay_map[i] != -1) {
1530            hwc_layer_1_t &layer =
1531                    contents->hwLayers[pdev->bufs.overlay_map[i]];
1532            int dup_fd = dup_or_warn(fence);
1533            if (pdev->bufs.gsc_map[i].mode == exynos5_gsc_map_t::GSC_M2M) {
1534                int gsc_idx = pdev->bufs.gsc_map[i].idx;
1535                exynos5_gsc_data_t &gsc = pdev->gsc[gsc_idx];
1536                gsc.dst_buf_fence[gsc.current_buf] = dup_fd;
1537                gsc.current_buf = (gsc.current_buf + 1) % NUM_GSC_DST_BUFS;
1538            } else {
1539                layer.releaseFenceFd = dup_fd;
1540            }
1541        }
1542    }
1543    contents->retireFenceFd = fence;
1544
1545    return err;
1546}
1547
1548static int exynos5_set_hdmi(exynos5_hwc_composer_device_1_t *pdev,
1549        hwc_display_contents_1_t* contents)
1550{
1551    hwc_layer_1_t *video_layer = NULL;
1552
1553    if (!pdev->hdmi_enabled) {
1554        for (size_t i = 0; i < contents->numHwLayers; i++) {
1555            hwc_layer_1_t &layer = contents->hwLayers[i];
1556            if (layer.acquireFenceFd != -1) {
1557                close(layer.acquireFenceFd);
1558                layer.acquireFenceFd = -1;
1559            }
1560        }
1561        return 0;
1562    }
1563
1564    for (size_t i = 0; i < contents->numHwLayers; i++) {
1565        hwc_layer_1_t &layer = contents->hwLayers[i];
1566
1567        if (layer.flags & HWC_SKIP_LAYER) {
1568            ALOGV("HDMI skipping layer %d", i);
1569            continue;
1570        }
1571
1572        if (layer.compositionType == HWC_OVERLAY) {
1573             if (!layer.handle)
1574                continue;
1575
1576            ALOGV("HDMI video layer:");
1577            dump_layer(&layer);
1578
1579            exynos5_gsc_data_t &gsc = pdev->gsc[HDMI_GSC_IDX];
1580            int ret = exynos5_config_gsc_m2m(layer, pdev->alloc_device, &gsc, 1,
1581                                             HAL_PIXEL_FORMAT_RGBX_8888, NULL);
1582            if (ret < 0) {
1583                ALOGE("failed to configure gscaler for video layer");
1584                continue;
1585            }
1586
1587            buffer_handle_t dst_buf = gsc.dst_buf[gsc.current_buf];
1588            private_handle_t *h = private_handle_t::dynamicCast(dst_buf);
1589
1590            int acquireFenceFd = gsc.dst_cfg.releaseFenceFd;
1591            int releaseFenceFd = -1;
1592
1593            hdmi_output(pdev, pdev->hdmi_layers[0], layer, h, acquireFenceFd,
1594                                                             &releaseFenceFd);
1595            video_layer = &layer;
1596
1597            gsc.dst_buf_fence[gsc.current_buf] = releaseFenceFd;
1598            gsc.current_buf = (gsc.current_buf + 1) % NUM_GSC_DST_BUFS;
1599            if (contents->retireFenceFd < 0)
1600                contents->retireFenceFd = dup_or_warn(releaseFenceFd);
1601            else {
1602                int merged = merge_or_warn("hdmi",
1603                        contents->retireFenceFd, layer.releaseFenceFd);
1604                close(contents->retireFenceFd);
1605                contents->retireFenceFd = merged;
1606            }
1607        }
1608
1609        if (layer.compositionType == HWC_FRAMEBUFFER_TARGET) {
1610            if (pdev->hdmi_fb_needed && layer.handle) {
1611                ALOGV("HDMI FB layer:");
1612                dump_layer(&layer);
1613
1614                private_handle_t *h = private_handle_t::dynamicCast(layer.handle);
1615                hdmi_show_layer(pdev, pdev->hdmi_layers[1]);
1616                hdmi_output(pdev, pdev->hdmi_layers[1], layer, h, layer.acquireFenceFd,
1617                                                                 &layer.releaseFenceFd);
1618
1619                if (contents->retireFenceFd < 0)
1620                    contents->retireFenceFd = dup_or_warn(layer.releaseFenceFd);
1621                else {
1622                    int merged = merge_or_warn("hdmi",
1623                            contents->retireFenceFd, layer.releaseFenceFd);
1624                    close(contents->retireFenceFd);
1625                    contents->retireFenceFd = merged;
1626                }
1627            } else {
1628                hdmi_hide_layer(pdev, pdev->hdmi_layers[1]);
1629            }
1630        }
1631    }
1632
1633    if (!video_layer) {
1634        hdmi_disable_layer(pdev, pdev->hdmi_layers[0]);
1635        exynos5_cleanup_gsc_m2m(pdev, HDMI_GSC_IDX);
1636    }
1637
1638    if (exynos_v4l2_s_ctrl(pdev->hdmi_layers[1].fd, V4L2_CID_TV_UPDATE, 1) < 0) {
1639        ALOGE("%s: s_ctrl(CID_TV_UPDATE) failed %d", __func__, errno);
1640        return -1;
1641    }
1642
1643    return 0;
1644}
1645
1646static int exynos5_set(struct hwc_composer_device_1 *dev,
1647        size_t numDisplays, hwc_display_contents_1_t** displays)
1648{
1649    if (!numDisplays || !displays)
1650        return 0;
1651
1652    exynos5_hwc_composer_device_1_t *pdev =
1653            (exynos5_hwc_composer_device_1_t *)dev;
1654    hwc_display_contents_1_t *fimd_contents = displays[HWC_DISPLAY_PRIMARY];
1655    hwc_display_contents_1_t *hdmi_contents = displays[HWC_DISPLAY_EXTERNAL];
1656    int fimd_err = 0, hdmi_err = 0;
1657
1658    if (fimd_contents)
1659        fimd_err = exynos5_set_fimd(pdev, fimd_contents);
1660
1661    if (hdmi_contents)
1662        hdmi_err = exynos5_set_hdmi(pdev, hdmi_contents);
1663
1664    if (fimd_err)
1665        return fimd_err;
1666
1667    return hdmi_err;
1668}
1669
1670static void exynos5_registerProcs(struct hwc_composer_device_1* dev,
1671        hwc_procs_t const* procs)
1672{
1673    struct exynos5_hwc_composer_device_1_t* pdev =
1674            (struct exynos5_hwc_composer_device_1_t*)dev;
1675    pdev->procs = procs;
1676}
1677
1678static int exynos5_query(struct hwc_composer_device_1* dev, int what, int *value)
1679{
1680    struct exynos5_hwc_composer_device_1_t *pdev =
1681            (struct exynos5_hwc_composer_device_1_t *)dev;
1682
1683    switch (what) {
1684    case HWC_BACKGROUND_LAYER_SUPPORTED:
1685        // we support the background layer
1686        value[0] = 1;
1687        break;
1688    case HWC_VSYNC_PERIOD:
1689        // vsync period in nanosecond
1690        value[0] = pdev->vsync_period;
1691        break;
1692    default:
1693        // unsupported query
1694        return -EINVAL;
1695    }
1696    return 0;
1697}
1698
1699static int exynos5_eventControl(struct hwc_composer_device_1 *dev, int dpy,
1700        int event, int enabled)
1701{
1702    struct exynos5_hwc_composer_device_1_t *pdev =
1703            (struct exynos5_hwc_composer_device_1_t *)dev;
1704
1705    switch (event) {
1706    case HWC_EVENT_VSYNC:
1707        __u32 val = !!enabled;
1708        int err = ioctl(pdev->fd, S3CFB_SET_VSYNC_INT, &val);
1709        if (err < 0) {
1710            ALOGE("vsync ioctl failed");
1711            return -errno;
1712        }
1713
1714        return 0;
1715    }
1716
1717    return -EINVAL;
1718}
1719
1720static void handle_hdmi_uevent(struct exynos5_hwc_composer_device_1_t *pdev,
1721        const char *buff, int len)
1722{
1723    const char *s = buff;
1724    s += strlen(s) + 1;
1725
1726    while (*s) {
1727        if (!strncmp(s, "SWITCH_STATE=", strlen("SWITCH_STATE=")))
1728            pdev->hdmi_hpd = atoi(s + strlen("SWITCH_STATE=")) == 1;
1729
1730        s += strlen(s) + 1;
1731        if (s - buff >= len)
1732            break;
1733    }
1734
1735    if (pdev->hdmi_hpd) {
1736        if (hdmi_get_config(pdev)) {
1737            ALOGE("Error reading HDMI configuration");
1738            pdev->hdmi_hpd = false;
1739            return;
1740        }
1741
1742        pdev->hdmi_blanked = false;
1743    }
1744
1745    ALOGV("HDMI HPD changed to %s", pdev->hdmi_hpd ? "enabled" : "disabled");
1746    if (pdev->hdmi_hpd)
1747        ALOGI("HDMI Resolution changed to %dx%d", pdev->hdmi_h, pdev->hdmi_w);
1748
1749    /* hwc_dev->procs is set right after the device is opened, but there is
1750     * still a race condition where a hotplug event might occur after the open
1751     * but before the procs are registered. */
1752    if (pdev->procs)
1753        pdev->procs->hotplug(pdev->procs, HWC_DISPLAY_EXTERNAL, pdev->hdmi_hpd);
1754}
1755
1756static void handle_vsync_event(struct exynos5_hwc_composer_device_1_t *pdev)
1757{
1758    if (!pdev->procs)
1759        return;
1760
1761    int err = lseek(pdev->vsync_fd, 0, SEEK_SET);
1762    if (err < 0) {
1763        ALOGE("error seeking to vsync timestamp: %s", strerror(errno));
1764        return;
1765    }
1766
1767    char buf[4096];
1768    err = read(pdev->vsync_fd, buf, sizeof(buf));
1769    if (err < 0) {
1770        ALOGE("error reading vsync timestamp: %s", strerror(errno));
1771        return;
1772    }
1773    buf[sizeof(buf) - 1] = '\0';
1774
1775    errno = 0;
1776    uint64_t timestamp = strtoull(buf, NULL, 0);
1777    if (!errno)
1778        pdev->procs->vsync(pdev->procs, 0, timestamp);
1779}
1780
1781static void *hwc_vsync_thread(void *data)
1782{
1783    struct exynos5_hwc_composer_device_1_t *pdev =
1784            (struct exynos5_hwc_composer_device_1_t *)data;
1785    char uevent_desc[4096];
1786    memset(uevent_desc, 0, sizeof(uevent_desc));
1787
1788    setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
1789
1790    uevent_init();
1791
1792    char temp[4096];
1793    int err = read(pdev->vsync_fd, temp, sizeof(temp));
1794    if (err < 0) {
1795        ALOGE("error reading vsync timestamp: %s", strerror(errno));
1796        return NULL;
1797    }
1798
1799    struct pollfd fds[2];
1800    fds[0].fd = pdev->vsync_fd;
1801    fds[0].events = POLLPRI;
1802    fds[1].fd = uevent_get_fd();
1803    fds[1].events = POLLIN;
1804
1805    while (true) {
1806        int err = poll(fds, 2, -1);
1807
1808        if (err > 0) {
1809            if (fds[0].revents & POLLPRI) {
1810                handle_vsync_event(pdev);
1811            }
1812            else if (fds[1].revents & POLLIN) {
1813                int len = uevent_next_event(uevent_desc,
1814                        sizeof(uevent_desc) - 2);
1815
1816                bool hdmi = !strcmp(uevent_desc,
1817                        "change@/devices/virtual/switch/hdmi");
1818                if (hdmi)
1819                    handle_hdmi_uevent(pdev, uevent_desc, len);
1820            }
1821        }
1822        else if (err == -1) {
1823            if (errno == EINTR)
1824                break;
1825            ALOGE("error in vsync thread: %s", strerror(errno));
1826        }
1827    }
1828
1829    return NULL;
1830}
1831
1832static int exynos5_blank(struct hwc_composer_device_1 *dev, int disp, int blank)
1833{
1834    struct exynos5_hwc_composer_device_1_t *pdev =
1835            (struct exynos5_hwc_composer_device_1_t *)dev;
1836
1837    switch (disp) {
1838    case HWC_DISPLAY_PRIMARY: {
1839        int fb_blank = blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK;
1840        int err = ioctl(pdev->fd, FBIOBLANK, fb_blank);
1841        if (err < 0) {
1842            if (errno == EBUSY)
1843                ALOGI("%sblank ioctl failed (display already %sblanked)",
1844                        blank ? "" : "un", blank ? "" : "un");
1845            else
1846                ALOGE("%sblank ioctl failed: %s", blank ? "" : "un",
1847                        strerror(errno));
1848            return -errno;
1849        }
1850        break;
1851    }
1852
1853    case HWC_DISPLAY_EXTERNAL:
1854        if (pdev->hdmi_hpd) {
1855            if (blank && !pdev->hdmi_blanked)
1856                hdmi_disable(pdev);
1857            pdev->hdmi_blanked = !!blank;
1858        }
1859        break;
1860
1861    default:
1862        return -EINVAL;
1863
1864    }
1865
1866    return 0;
1867}
1868
1869static void exynos5_dump(hwc_composer_device_1* dev, char *buff, int buff_len)
1870{
1871    if (buff_len <= 0)
1872        return;
1873
1874    struct exynos5_hwc_composer_device_1_t *pdev =
1875            (struct exynos5_hwc_composer_device_1_t *)dev;
1876
1877    android::String8 result;
1878
1879    result.appendFormat("  hdmi_enabled=%u\n", pdev->hdmi_enabled);
1880    if (pdev->hdmi_enabled)
1881        result.appendFormat("    w=%u, h=%u\n", pdev->hdmi_w, pdev->hdmi_h);
1882    result.append(
1883            "   type   |  handle  |  color   | blend | format |   position    |     size      | gsc \n"
1884            "----------+----------|----------+-------+--------+---------------+---------------------\n");
1885    //        8_______ | 8_______ | 8_______ | 5____ | 6_____ | [5____,5____] | [5____,5____] | 3__ \n"
1886
1887    for (size_t i = 0; i < NUM_HW_WINDOWS; i++) {
1888        struct s3c_fb_win_config &config = pdev->last_config[i];
1889        if (config.state == config.S3C_FB_WIN_STATE_DISABLED) {
1890            result.appendFormat(" %8s | %8s | %8s | %5s | %6s | %13s | %13s",
1891                    "DISABLED", "-", "-", "-", "-", "-", "-");
1892        }
1893        else {
1894            if (config.state == config.S3C_FB_WIN_STATE_COLOR)
1895                result.appendFormat(" %8s | %8s | %8x | %5s | %6s", "COLOR",
1896                        "-", config.color, "-", "-");
1897            else
1898                result.appendFormat(" %8s | %8x | %8s | %5x | %6x",
1899                        pdev->last_fb_window == i ? "FB" : "OVERLAY",
1900                        intptr_t(pdev->last_handles[i]),
1901                        "-", config.blending, config.format);
1902
1903            result.appendFormat(" | [%5d,%5d] | [%5u,%5u]", config.x, config.y,
1904                    config.w, config.h);
1905        }
1906        if (pdev->last_gsc_map[i].mode == exynos5_gsc_map_t::GSC_NONE)
1907            result.appendFormat(" | %3s", "-");
1908        else
1909            result.appendFormat(" | %3d",
1910                    AVAILABLE_GSC_UNITS[pdev->last_gsc_map[i].idx]);
1911        result.append("\n");
1912    }
1913
1914    strlcpy(buff, result.string(), buff_len);
1915}
1916
1917static int exynos5_getDisplayConfigs(struct hwc_composer_device_1 *dev,
1918        int disp, uint32_t *configs, size_t *numConfigs)
1919{
1920    struct exynos5_hwc_composer_device_1_t *pdev =
1921               (struct exynos5_hwc_composer_device_1_t *)dev;
1922
1923    if (*numConfigs == 0)
1924        return 0;
1925
1926    if (disp == HWC_DISPLAY_PRIMARY) {
1927        configs[0] = 0;
1928        *numConfigs = 1;
1929        return 0;
1930    } else if (disp == HWC_DISPLAY_EXTERNAL) {
1931        if (!pdev->hdmi_hpd) {
1932            return -EINVAL;
1933        }
1934
1935        int err = hdmi_get_config(pdev);
1936        if (err) {
1937            return -EINVAL;
1938        }
1939
1940        configs[0] = 0;
1941        *numConfigs = 1;
1942        return 0;
1943    }
1944
1945    return -EINVAL;
1946}
1947
1948static int32_t exynos5_fimd_attribute(struct exynos5_hwc_composer_device_1_t *pdev,
1949        const uint32_t attribute)
1950{
1951    switch(attribute) {
1952    case HWC_DISPLAY_VSYNC_PERIOD:
1953        return pdev->vsync_period;
1954
1955    case HWC_DISPLAY_WIDTH:
1956        return pdev->xres;
1957
1958    case HWC_DISPLAY_HEIGHT:
1959        return pdev->yres;
1960
1961    case HWC_DISPLAY_DPI_X:
1962        return pdev->xdpi;
1963
1964    case HWC_DISPLAY_DPI_Y:
1965        return pdev->ydpi;
1966
1967    default:
1968        ALOGE("unknown display attribute %u", attribute);
1969        return -EINVAL;
1970    }
1971}
1972
1973static int32_t exynos5_hdmi_attribute(struct exynos5_hwc_composer_device_1_t *pdev,
1974        const uint32_t attribute)
1975{
1976    switch(attribute) {
1977    case HWC_DISPLAY_VSYNC_PERIOD:
1978        return pdev->vsync_period;
1979
1980    case HWC_DISPLAY_WIDTH:
1981        return pdev->hdmi_w;
1982
1983    case HWC_DISPLAY_HEIGHT:
1984        return pdev->hdmi_h;
1985
1986    case HWC_DISPLAY_DPI_X:
1987    case HWC_DISPLAY_DPI_Y:
1988        return 0; // unknown
1989
1990    default:
1991        ALOGE("unknown display attribute %u", attribute);
1992        return -EINVAL;
1993    }
1994}
1995
1996static int exynos5_getDisplayAttributes(struct hwc_composer_device_1 *dev,
1997        int disp, uint32_t config, const uint32_t *attributes, int32_t *values)
1998{
1999    struct exynos5_hwc_composer_device_1_t *pdev =
2000                   (struct exynos5_hwc_composer_device_1_t *)dev;
2001
2002    for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
2003        if (disp == HWC_DISPLAY_PRIMARY)
2004            values[i] = exynos5_fimd_attribute(pdev, attributes[i]);
2005        else if (disp == HWC_DISPLAY_EXTERNAL)
2006            values[i] = exynos5_hdmi_attribute(pdev, attributes[i]);
2007        else {
2008            ALOGE("unknown display type %u", disp);
2009            return -EINVAL;
2010        }
2011    }
2012
2013    return 0;
2014}
2015
2016static int exynos5_close(hw_device_t* device);
2017
2018static int exynos5_open(const struct hw_module_t *module, const char *name,
2019        struct hw_device_t **device)
2020{
2021    int ret;
2022    int refreshRate;
2023    int sw_fd;
2024
2025    if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
2026        return -EINVAL;
2027    }
2028
2029    struct exynos5_hwc_composer_device_1_t *dev;
2030    dev = (struct exynos5_hwc_composer_device_1_t *)malloc(sizeof(*dev));
2031    memset(dev, 0, sizeof(*dev));
2032
2033    if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
2034            (const struct hw_module_t **)&dev->gralloc_module)) {
2035        ALOGE("failed to get gralloc hw module");
2036        ret = -EINVAL;
2037        goto err_get_module;
2038    }
2039
2040    if (gralloc_open((const hw_module_t *)dev->gralloc_module,
2041            &dev->alloc_device)) {
2042        ALOGE("failed to open gralloc");
2043        ret = -EINVAL;
2044        goto err_get_module;
2045    }
2046
2047    dev->fd = open("/dev/graphics/fb0", O_RDWR);
2048    if (dev->fd < 0) {
2049        ALOGE("failed to open framebuffer");
2050        ret = dev->fd;
2051        goto err_open_fb;
2052    }
2053
2054    struct fb_var_screeninfo info;
2055    if (ioctl(dev->fd, FBIOGET_VSCREENINFO, &info) == -1) {
2056        ALOGE("FBIOGET_VSCREENINFO ioctl failed: %s", strerror(errno));
2057        ret = -errno;
2058        goto err_ioctl;
2059    }
2060
2061    refreshRate = 1000000000000LLU /
2062        (
2063         uint64_t( info.upper_margin + info.lower_margin + info.yres )
2064         * ( info.left_margin  + info.right_margin + info.xres )
2065         * info.pixclock
2066        );
2067
2068    if (refreshRate == 0) {
2069        ALOGW("invalid refresh rate, assuming 60 Hz");
2070        refreshRate = 60;
2071    }
2072
2073    dev->xres = 2560;
2074    dev->yres = 1600;
2075    dev->xdpi = 1000 * (info.xres * 25.4f) / info.width;
2076    dev->ydpi = 1000 * (info.yres * 25.4f) / info.height;
2077    dev->vsync_period  = 1000000000 / refreshRate;
2078
2079    ALOGV("using\n"
2080          "xres         = %d px\n"
2081          "yres         = %d px\n"
2082          "width        = %d mm (%f dpi)\n"
2083          "height       = %d mm (%f dpi)\n"
2084          "refresh rate = %d Hz\n",
2085          dev->xres, dev->yres, info.width, dev->xdpi / 1000.0,
2086          info.height, dev->ydpi / 1000.0, refreshRate);
2087
2088    for (size_t i = 0; i < NUM_GSC_UNITS; i++)
2089        for (size_t j = 0; j < NUM_GSC_DST_BUFS; j++)
2090            dev->gsc[i].dst_buf_fence[j] = -1;
2091
2092    dev->hdmi_mixer0 = open("/dev/v4l-subdev7", O_RDWR);
2093    if (dev->hdmi_mixer0 < 0)
2094        ALOGE("failed to open hdmi mixer0 subdev");
2095
2096    dev->hdmi_layers[0].id = 0;
2097    dev->hdmi_layers[0].fd = open("/dev/video16", O_RDWR);
2098    if (dev->hdmi_layers[0].fd < 0) {
2099        ALOGE("failed to open hdmi layer0 device");
2100        ret = dev->hdmi_layers[0].fd;
2101        goto err_mixer0;
2102    }
2103
2104    dev->hdmi_layers[1].id = 1;
2105    dev->hdmi_layers[1].fd = open("/dev/video17", O_RDWR);
2106    if (dev->hdmi_layers[1].fd < 0) {
2107        ALOGE("failed to open hdmi layer1 device");
2108        ret = dev->hdmi_layers[1].fd;
2109        goto err_hdmi0;
2110    }
2111
2112    dev->vsync_fd = open("/sys/devices/platform/exynos5-fb.1/vsync", O_RDONLY);
2113    if (dev->vsync_fd < 0) {
2114        ALOGE("failed to open vsync attribute");
2115        ret = dev->vsync_fd;
2116        goto err_hdmi1;
2117    }
2118
2119    sw_fd = open("/sys/class/switch/hdmi/state", O_RDONLY);
2120    if (sw_fd) {
2121        char val;
2122        if (read(sw_fd, &val, 1) == 1 && val == '1') {
2123            dev->hdmi_hpd = true;
2124            if (hdmi_get_config(dev)) {
2125                ALOGE("Error reading HDMI configuration");
2126                dev->hdmi_hpd = false;
2127            }
2128        }
2129    }
2130
2131    dev->base.common.tag = HARDWARE_DEVICE_TAG;
2132    dev->base.common.version = HWC_DEVICE_API_VERSION_1_1;
2133    dev->base.common.module = const_cast<hw_module_t *>(module);
2134    dev->base.common.close = exynos5_close;
2135
2136    dev->base.prepare = exynos5_prepare;
2137    dev->base.set = exynos5_set;
2138    dev->base.eventControl = exynos5_eventControl;
2139    dev->base.blank = exynos5_blank;
2140    dev->base.query = exynos5_query;
2141    dev->base.registerProcs = exynos5_registerProcs;
2142    dev->base.dump = exynos5_dump;
2143    dev->base.getDisplayConfigs = exynos5_getDisplayConfigs;
2144    dev->base.getDisplayAttributes = exynos5_getDisplayAttributes;
2145
2146    *device = &dev->base.common;
2147
2148    ret = pthread_create(&dev->vsync_thread, NULL, hwc_vsync_thread, dev);
2149    if (ret) {
2150        ALOGE("failed to start vsync thread: %s", strerror(ret));
2151        ret = -ret;
2152        goto err_vsync;
2153    }
2154
2155    char value[PROPERTY_VALUE_MAX];
2156    property_get("debug.hwc.force_gpu", value, "0");
2157    dev->force_gpu = atoi(value);
2158
2159    return 0;
2160
2161err_vsync:
2162    close(dev->vsync_fd);
2163err_mixer0:
2164    if (dev->hdmi_mixer0 >= 0)
2165        close(dev->hdmi_mixer0);
2166err_hdmi1:
2167    close(dev->hdmi_layers[0].fd);
2168err_hdmi0:
2169    close(dev->hdmi_layers[1].fd);
2170err_ioctl:
2171    close(dev->fd);
2172err_open_fb:
2173    gralloc_close(dev->alloc_device);
2174err_get_module:
2175    free(dev);
2176    return ret;
2177}
2178
2179static int exynos5_close(hw_device_t *device)
2180{
2181    struct exynos5_hwc_composer_device_1_t *dev =
2182            (struct exynos5_hwc_composer_device_1_t *)device;
2183    pthread_kill(dev->vsync_thread, SIGTERM);
2184    pthread_join(dev->vsync_thread, NULL);
2185    for (size_t i = 0; i < NUM_GSC_UNITS; i++)
2186        exynos5_cleanup_gsc_m2m(dev, i);
2187    gralloc_close(dev->alloc_device);
2188    close(dev->vsync_fd);
2189    if (dev->hdmi_mixer0 >= 0)
2190        close(dev->hdmi_mixer0);
2191    close(dev->hdmi_layers[0].fd);
2192    close(dev->hdmi_layers[1].fd);
2193    close(dev->fd);
2194    return 0;
2195}
2196
2197static struct hw_module_methods_t exynos5_hwc_module_methods = {
2198    open: exynos5_open,
2199};
2200
2201hwc_module_t HAL_MODULE_INFO_SYM = {
2202    common: {
2203        tag: HARDWARE_MODULE_TAG,
2204        module_api_version: HWC_MODULE_API_VERSION_0_1,
2205        hal_api_version: HARDWARE_HAL_API_VERSION,
2206        id: HWC_HARDWARE_MODULE_ID,
2207        name: "Samsung exynos5 hwcomposer module",
2208        author: "Google",
2209        methods: &exynos5_hwc_module_methods,
2210    }
2211};
2212