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