1/*
2 * Copyright (C) Texas Instruments - http://www.ti.com/
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
17#include <errno.h>
18#include <malloc.h>
19#include <stdlib.h>
20#include <stdarg.h>
21#include <fcntl.h>
22#include <poll.h>
23#include <sys/ioctl.h>
24#include <linux/fb.h>
25#include <sys/mman.h>
26
27#include <cutils/properties.h>
28#include <cutils/log.h>
29#include <cutils/native_handle.h>
30#include <hardware/hardware.h>
31#include <hardware/hwcomposer.h>
32#include <EGL/egl.h>
33#include <utils/Timers.h>
34#include <hardware_legacy/uevent.h>
35#include <png.h>
36
37#define ASPECT_RATIO_TOLERANCE 0.02f
38
39#ifndef FBIO_WAITFORVSYNC
40#define FBIO_WAITFORVSYNC       _IOW('F', 0x20, __u32)
41#endif
42
43#define min(a, b) ( { typeof(a) __a = (a), __b = (b); __a < __b ? __a : __b; } )
44#define max(a, b) ( { typeof(a) __a = (a), __b = (b); __a > __b ? __a : __b; } )
45#define swap(a, b) do { typeof(a) __a = (a); (a) = (b); (b) = __a; } while (0)
46
47#define WIDTH(rect) ((rect).right - (rect).left)
48#define HEIGHT(rect) ((rect).bottom - (rect).top)
49
50#include <video/dsscomp.h>
51
52#include "hal_public.h"
53
54#define MAX_HW_OVERLAYS 4
55#define NUM_NONSCALING_OVERLAYS 1
56#define HAL_PIXEL_FORMAT_BGRX_8888      0x1FF
57#define HAL_PIXEL_FORMAT_TI_NV12        0x100
58#define HAL_PIXEL_FORMAT_TI_NV12_PADDED 0x101
59#define MAX_TILER_SLOT (16 << 20)
60
61struct ext_transform_t {
62    __u8 rotation : 3;          /* 90-degree clockwise rotations */
63    __u8 hflip    : 1;          /* flip l-r (after rotation) */
64    __u8 enabled  : 1;          /* cloning enabled */
65    __u8 docking  : 1;          /* docking vs. mirroring - used for state */
66};
67
68/* cloning support and state */
69struct omap4_hwc_ext {
70    /* support */
71    struct ext_transform_t mirror;      /* mirroring settings */
72    struct ext_transform_t dock;        /* docking settings */
73    float lcd_xpy;                      /* pixel ratio for UI */
74    __u8 avoid_mode_change;             /* use HDMI mode used for mirroring if possible */
75    __u8 force_dock;                     /* must dock */
76    __u8 hdmi_state;                     /* whether HDMI is connected */
77
78    /* state */
79    __u8 on_tv;                         /* using a tv */
80    struct ext_transform_t current;     /* current settings */
81    struct ext_transform_t last;        /* last-used settings */
82
83    /* configuration */
84    __u32 last_xres_used;               /* resolution and pixel ratio used for mode selection */
85    __u32 last_yres_used;
86    __u32 last_mode;                    /* 2-s complement of last HDMI mode set, 0 if none */
87    __u32 mirror_mode;                  /* 2-s complement of mode used when mirroring */
88    float last_xpy;
89    __u16 width;                        /* external screen dimensions */
90    __u16 height;
91    __u32 xres;                         /* external screen resolution */
92    __u32 yres;
93    float m[2][3];                      /* external transformation matrix */
94    hwc_rect_t mirror_region;           /* region of screen to mirror */
95};
96typedef struct omap4_hwc_ext omap4_hwc_ext_t;
97
98/* used by property settings */
99enum {
100    EXT_ROTATION    = 3,        /* rotation while mirroring */
101    EXT_HFLIP       = (1 << 2), /* flip l-r on output (after rotation) */
102};
103
104/* ARGB image */
105struct omap4_hwc_img {
106    int width;
107    int height;
108    int rowbytes;
109    int size;
110    unsigned char *ptr;
111} dock_image = { .rowbytes = 0 };
112
113struct omap4_hwc_module {
114    hwc_module_t base;
115
116    IMG_framebuffer_device_public_t *fb_dev;
117};
118typedef struct omap4_hwc_module omap4_hwc_module_t;
119
120struct omap4_hwc_device {
121    /* static data */
122    hwc_composer_device_t base;
123    hwc_procs_t *procs;
124    pthread_t hdmi_thread;
125    pthread_mutex_t lock;
126
127    IMG_framebuffer_device_public_t *fb_dev;
128    struct dsscomp_display_info fb_dis;
129    int fb_fd;                  /* file descriptor for /dev/fb0 */
130    int dsscomp_fd;             /* file descriptor for /dev/dsscomp */
131    int hdmi_fb_fd;             /* file descriptor for /dev/fb1 */
132    int pipe_fds[2];            /* pipe to event thread */
133
134    int img_mem_size;           /* size of fb for hdmi */
135    void *img_mem_ptr;          /* start of fb for hdmi */
136
137    int flags_rgb_order;
138    int flags_nv12_only;
139
140    int force_sgx;
141    omap4_hwc_ext_t ext;        /* external mirroring data */
142    int idle;
143    int ovls_blending;
144
145    /* composition data */
146    struct dsscomp_setup_dispc_data dsscomp_data;
147    buffer_handle_t *buffers;
148    int use_sgx;
149    int swap_rb;
150    unsigned int post2_layers;
151    int ext_ovls;               /* # of overlays on external display for current composition */
152    int ext_ovls_wanted;        /* # of overlays that should be on external display for current composition */
153    int last_ext_ovls;          /* # of overlays on external/internal display for last composition */
154    int last_int_ovls;
155};
156typedef struct omap4_hwc_device omap4_hwc_device_t;
157
158#define HAL_FMT(f) ((f) == HAL_PIXEL_FORMAT_TI_NV12 ? "NV12" : \
159                    (f) == HAL_PIXEL_FORMAT_YV12 ? "YV12" : \
160                    (f) == HAL_PIXEL_FORMAT_BGRX_8888 ? "xRGB32" : \
161                    (f) == HAL_PIXEL_FORMAT_RGBX_8888 ? "xBGR32" : \
162                    (f) == HAL_PIXEL_FORMAT_BGRA_8888 ? "ARGB32" : \
163                    (f) == HAL_PIXEL_FORMAT_RGBA_8888 ? "ABGR32" : \
164                    (f) == HAL_PIXEL_FORMAT_RGB_565 ? "RGB565" : "??")
165
166#define DSS_FMT(f) ((f) == OMAP_DSS_COLOR_NV12 ? "NV12" : \
167                    (f) == OMAP_DSS_COLOR_RGB24U ? "xRGB32" : \
168                    (f) == OMAP_DSS_COLOR_ARGB32 ? "ARGB32" : \
169                    (f) == OMAP_DSS_COLOR_RGB16 ? "RGB565" : "??")
170
171static int debug = 0;
172
173static void dump_layer(hwc_layer_t const* l)
174{
175    LOGD("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}",
176         l->compositionType, l->flags, l->handle, l->transform, l->blending,
177         l->sourceCrop.left,
178         l->sourceCrop.top,
179         l->sourceCrop.right,
180         l->sourceCrop.bottom,
181         l->displayFrame.left,
182         l->displayFrame.top,
183         l->displayFrame.right,
184         l->displayFrame.bottom);
185}
186
187static void dump_dsscomp(struct dsscomp_setup_dispc_data *d)
188{
189    unsigned i;
190
191    LOGD("[%08x] set: %c%c%c %d ovls\n",
192         d->sync_id,
193         (d->mode & DSSCOMP_SETUP_MODE_APPLY) ? 'A' : '-',
194         (d->mode & DSSCOMP_SETUP_MODE_DISPLAY) ? 'D' : '-',
195         (d->mode & DSSCOMP_SETUP_MODE_CAPTURE) ? 'C' : '-',
196         d->num_ovls);
197
198    for (i = 0; i < d->num_mgrs; i++) {
199        struct dss2_mgr_info *mi = &d->mgrs[i];
200        LOGD(" (dis%d alpha=%d col=%08x ilace=%d)\n",
201             mi->ix,
202             mi->alpha_blending, mi->default_color,
203             mi->interlaced);
204    }
205
206    for (i = 0; i < d->num_ovls; i++) {
207        struct dss2_ovl_info *oi = &d->ovls[i];
208        struct dss2_ovl_cfg *c = &oi->cfg;
209        if (c->zonly)
210            LOGD("ovl%d(%s z%d)\n",
211                 c->ix, c->enabled ? "ON" : "off", c->zorder);
212        else
213            LOGD("ovl%d(%s z%d %s%s *%d%% %d*%d:%d,%d+%d,%d rot%d%s => %d,%d+%d,%d %p/%p|%d)\n",
214                 c->ix, c->enabled ? "ON" : "off", c->zorder, DSS_FMT(c->color_mode),
215                 c->pre_mult_alpha ? " premult" : "",
216                 (c->global_alpha * 100 + 128) / 255,
217                 c->width, c->height, c->crop.x, c->crop.y,
218                 c->crop.w, c->crop.h,
219                 c->rotation, c->mirror ? "+mir" : "",
220                 c->win.x, c->win.y, c->win.w, c->win.h,
221                 (void *) oi->ba, (void *) oi->uv, c->stride);
222    }
223}
224
225struct dump_buf {
226    char *buf;
227    int buf_len;
228    int len;
229};
230
231static void dump_printf(struct dump_buf *buf, const char *fmt, ...)
232{
233    va_list ap;
234
235    va_start(ap, fmt);
236    buf->len += vsnprintf(buf->buf + buf->len, buf->buf_len - buf->len, fmt, ap);
237    va_end(ap);
238}
239
240static void dump_set_info(omap4_hwc_device_t *hwc_dev, hwc_layer_list_t* list)
241{
242    struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->dsscomp_data;
243    char logbuf[1024];
244    struct dump_buf log = {
245        .buf = logbuf,
246        .buf_len = sizeof(logbuf),
247    };
248    unsigned int i;
249
250    dump_printf(&log, "set H{");
251    for (i = 0; list && i < list->numHwLayers; i++) {
252        if (i)
253            dump_printf(&log, " ");
254        hwc_layer_t *layer = &list->hwLayers[i];
255        IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
256        dump_printf(&log, "%p:%s,", handle, layer->compositionType == HWC_OVERLAY ? "DSS" : "SGX");
257        if ((layer->flags & HWC_SKIP_LAYER) || !handle) {
258            dump_printf(&log, "SKIP");
259            continue;
260        }
261        if (layer->flags & HWC_HINT_CLEAR_FB)
262            dump_printf(&log, "CLR,");
263        dump_printf(&log, "%d*%d(%s)", handle->iWidth, handle->iHeight, HAL_FMT(handle->iFormat));
264        if (layer->transform)
265            dump_printf(&log, "~%d", layer->transform);
266    }
267    dump_printf(&log, "} D{");
268    for (i = 0; i < dsscomp->num_ovls; i++) {
269        if (i)
270            dump_printf(&log, " ");
271        dump_printf(&log, "%d=", dsscomp->ovls[i].cfg.ix);
272        if (dsscomp->ovls[i].cfg.enabled)
273            dump_printf(&log, "%08x:%d*%d,%s",
274                        dsscomp->ovls[i].ba,
275                        dsscomp->ovls[i].cfg.width,
276                        dsscomp->ovls[i].cfg.height,
277                        DSS_FMT(dsscomp->ovls[i].cfg.color_mode));
278        else
279            dump_printf(&log, "-");
280    }
281    dump_printf(&log, "} L{");
282    for (i = 0; i < hwc_dev->post2_layers; i++) {
283        if (i)
284            dump_printf(&log, " ");
285        dump_printf(&log, "%p", hwc_dev->buffers[i]);
286    }
287    dump_printf(&log, "}%s\n", hwc_dev->use_sgx ? " swap" : "");
288
289    LOGD("%s", log.buf);
290}
291
292static int sync_id = 0;
293
294static int omap4_hwc_is_valid_format(int format)
295{
296    switch(format) {
297    case HAL_PIXEL_FORMAT_RGB_565:
298    case HAL_PIXEL_FORMAT_RGBX_8888:
299    case HAL_PIXEL_FORMAT_RGBA_8888:
300    case HAL_PIXEL_FORMAT_BGRA_8888:
301    case HAL_PIXEL_FORMAT_BGRX_8888:
302    case HAL_PIXEL_FORMAT_TI_NV12:
303    case HAL_PIXEL_FORMAT_TI_NV12_PADDED:
304        return 1;
305
306    default:
307        return 0;
308    }
309}
310
311static int scaled(hwc_layer_t *layer)
312{
313    int w = WIDTH(layer->sourceCrop);
314    int h = HEIGHT(layer->sourceCrop);
315
316    if (layer->transform & HWC_TRANSFORM_ROT_90)
317        swap(w, h);
318
319    return WIDTH(layer->displayFrame) != w || HEIGHT(layer->displayFrame) != h;
320}
321
322static int is_protected(hwc_layer_t *layer)
323{
324    IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
325
326    return (handle->usage & GRALLOC_USAGE_PROTECTED);
327}
328
329#define is_BLENDED(layer) ((layer)->blending != HWC_BLENDING_NONE)
330
331static int is_RGB(IMG_native_handle_t *handle)
332{
333    switch(handle->iFormat)
334    {
335    case HAL_PIXEL_FORMAT_BGRA_8888:
336    case HAL_PIXEL_FORMAT_BGRX_8888:
337    case HAL_PIXEL_FORMAT_RGB_565:
338        return 1;
339    default:
340        return 0;
341    }
342}
343
344static int is_BGR_format(int format)
345{
346    switch (format) {
347    case HAL_PIXEL_FORMAT_RGBX_8888:
348    case HAL_PIXEL_FORMAT_RGBA_8888:
349        return 1;
350    default:
351        return 0;
352    }
353}
354
355static int is_BGR(IMG_native_handle_t *handle)
356{
357    return is_BGR_format(handle->iFormat);
358}
359
360static int is_NV12(IMG_native_handle_t *handle)
361{
362    switch(handle->iFormat)
363    {
364    case HAL_PIXEL_FORMAT_TI_NV12:
365    case HAL_PIXEL_FORMAT_TI_NV12_PADDED:
366        return 1;
367    default:
368        return 0;
369    }
370}
371
372static int dockable(hwc_layer_t *layer)
373{
374    IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
375
376    return (handle->usage & GRALLOC_USAGE_EXTERNAL_DISP);
377}
378
379static unsigned int mem1d(IMG_native_handle_t *handle)
380{
381    if (handle == NULL || is_NV12(handle))
382        return 0;
383
384    int bpp = handle->iFormat == HAL_PIXEL_FORMAT_RGB_565 ? 2 : 4;
385    int stride = ALIGN(handle->iWidth, HW_ALIGN) * bpp;
386    return stride * handle->iHeight;
387}
388
389static void
390omap4_hwc_setup_layer_base(struct dss2_ovl_cfg *oc, int index, int format, int blended, int width, int height)
391{
392    unsigned int bits_per_pixel;
393
394    /* YUV2RGB conversion */
395    const struct omap_dss_cconv_coefs ctbl_bt601_5 = {
396        298,  409,    0,  298, -208, -100,  298,    0,  517, 0,
397    };
398
399    /* convert color format */
400    switch (format) {
401    case HAL_PIXEL_FORMAT_RGBA_8888:
402    case HAL_PIXEL_FORMAT_BGRA_8888:
403        oc->color_mode = OMAP_DSS_COLOR_ARGB32;
404        bits_per_pixel = 32;
405        if (blended)
406                break;
407
408    case HAL_PIXEL_FORMAT_RGBX_8888:
409    case HAL_PIXEL_FORMAT_BGRX_8888:
410        oc->color_mode = OMAP_DSS_COLOR_RGB24U;
411        bits_per_pixel = 32;
412        break;
413
414    case HAL_PIXEL_FORMAT_RGB_565:
415        oc->color_mode = OMAP_DSS_COLOR_RGB16;
416        bits_per_pixel = 16;
417        break;
418
419    case HAL_PIXEL_FORMAT_TI_NV12:
420    case HAL_PIXEL_FORMAT_TI_NV12_PADDED:
421        oc->color_mode = OMAP_DSS_COLOR_NV12;
422        bits_per_pixel = 8;
423        oc->cconv = ctbl_bt601_5;
424        break;
425
426    default:
427        /* Should have been filtered out */
428        LOGV("Unsupported pixel format");
429        return;
430    }
431
432    oc->width = width;
433    oc->height = height;
434    oc->stride = ALIGN(width, HW_ALIGN) * bits_per_pixel / 8;
435
436    oc->enabled = 1;
437    oc->global_alpha = 255;
438    oc->zorder = index;
439    oc->ix = 0;
440
441    /* defaults for SGX framebuffer renders */
442    oc->crop.w = oc->win.w = width;
443    oc->crop.h = oc->win.h = height;
444
445    /* for now interlacing and vc1 info is not supplied */
446    oc->ilace = OMAP_DSS_ILACE_NONE;
447    oc->vc1.enable = 0;
448}
449
450static void
451omap4_hwc_setup_layer(omap4_hwc_device_t *hwc_dev, struct dss2_ovl_info *ovl,
452                      hwc_layer_t *layer, int index,
453                      int format, int width, int height)
454{
455    struct dss2_ovl_cfg *oc = &ovl->cfg;
456
457    //dump_layer(layer);
458
459    omap4_hwc_setup_layer_base(oc, index, format, is_BLENDED(layer), width, height);
460
461    /* convert transformation - assuming 0-set config */
462    if (layer->transform & HWC_TRANSFORM_FLIP_H)
463        oc->mirror = 1;
464    if (layer->transform & HWC_TRANSFORM_FLIP_V) {
465        oc->rotation = 2;
466        oc->mirror = !oc->mirror;
467    }
468    if (layer->transform & HWC_TRANSFORM_ROT_90) {
469        oc->rotation += oc->mirror ? -1 : 1;
470        oc->rotation &= 3;
471    }
472
473    oc->pre_mult_alpha = layer->blending == HWC_BLENDING_PREMULT;
474
475    /* display position */
476    oc->win.x = layer->displayFrame.left;
477    oc->win.y = layer->displayFrame.top;
478    oc->win.w = WIDTH(layer->displayFrame);
479    oc->win.h = HEIGHT(layer->displayFrame);
480
481    /* crop */
482    oc->crop.x = layer->sourceCrop.left;
483    oc->crop.y = layer->sourceCrop.top;
484    oc->crop.w = WIDTH(layer->sourceCrop);
485    oc->crop.h = HEIGHT(layer->sourceCrop);
486}
487
488const float m_unit[2][3] = { { 1., 0., 0. }, { 0., 1., 0. } };
489
490static inline void m_translate(float m[2][3], int dx, int dy)
491{
492    m[0][2] += dx;
493    m[1][2] += dy;
494}
495
496static inline void m_scale1(float m[3], int from, int to)
497{
498    m[0] = m[0] * to / from;
499    m[1] = m[1] * to / from;
500    m[2] = m[2] * to / from;
501}
502
503static inline void m_scale(float m[2][3], int x_from, int x_to, int y_from, int y_to)
504{
505    m_scale1(m[0], x_from, x_to);
506    m_scale1(m[1], y_from, y_to);
507}
508
509static void m_rotate(float m[2][3], int quarter_turns)
510{
511    if (quarter_turns & 2)
512        m_scale(m, 1, -1, 1, -1);
513    if (quarter_turns & 1) {
514        int q;
515        q = m[0][0]; m[0][0] = -m[1][0]; m[1][0] = q;
516        q = m[0][1]; m[0][1] = -m[1][1]; m[1][1] = q;
517        q = m[0][2]; m[0][2] = -m[1][2]; m[1][2] = q;
518    }
519}
520
521static inline int m_round(float x)
522{
523    /* int truncates towards 0 */
524    return (int) (x < 0 ? x - 0.5 : x + 0.5);
525}
526
527/*
528 * assuming xpy (xratio:yratio) original pixel ratio, calculate the adjusted width
529 * and height for a screen of xres/yres and physical size of width/height.
530 * The adjusted size is the largest that fits into the screen.
531 */
532static void get_max_dimensions(__u32 orig_xres, __u32 orig_yres,
533                               float xpy,
534                               __u32 scr_xres, __u32 scr_yres,
535                               __u32 scr_width, __u32 scr_height,
536                               __u32 *adj_xres, __u32 *adj_yres)
537{
538    /* assume full screen (largest size)*/
539    *adj_xres = scr_xres;
540    *adj_yres = scr_yres;
541
542    /* assume 1:1 pixel ratios if none supplied */
543    if (!scr_width || !scr_height) {
544        scr_width = scr_xres;
545        scr_height = scr_yres;
546    }
547
548    /* trim to keep aspect ratio */
549    float x_factor = orig_xres * xpy * scr_height;
550    float y_factor = orig_yres *       scr_width;
551
552    /* allow for tolerance so we avoid scaling if framebuffer is standard size */
553    if (x_factor < y_factor * (1.f - ASPECT_RATIO_TOLERANCE))
554        *adj_xres = (__u32) (x_factor * *adj_xres / y_factor + 0.5);
555    else if (x_factor * (1.f - ASPECT_RATIO_TOLERANCE) > y_factor)
556        *adj_yres = (__u32) (y_factor * *adj_yres / x_factor + 0.5);
557}
558
559static void set_ext_matrix(omap4_hwc_ext_t *ext, struct hwc_rect region)
560{
561    int orig_w = WIDTH(region);
562    int orig_h = HEIGHT(region);
563    float xpy = ext->lcd_xpy;
564
565    /* reorientation matrix is:
566       m = (center-from-target-center) * (scale-to-target) * (mirror) * (rotate) * (center-to-original-center) */
567
568    memcpy(ext->m, m_unit, sizeof(m_unit));
569    m_translate(ext->m, -(orig_w >> 1) - region.left, -(orig_h >> 1) - region.top);
570    m_rotate(ext->m, ext->current.rotation);
571    if (ext->current.hflip)
572        m_scale(ext->m, 1, -1, 1, 1);
573
574    if (ext->current.rotation & 1) {
575        swap(orig_w, orig_h);
576        xpy = 1. / xpy;
577    }
578
579    /* get target size */
580    __u32 adj_xres, adj_yres;
581    get_max_dimensions(orig_w, orig_h, xpy,
582                       ext->xres, ext->yres, ext->width, ext->height,
583                       &adj_xres, &adj_yres);
584
585    m_scale(ext->m, orig_w, adj_xres, orig_h, adj_yres);
586    m_translate(ext->m, ext->xres >> 1, ext->yres >> 1);
587}
588
589static int
590crop_to_rect(struct dss2_ovl_cfg *cfg, struct hwc_rect vis_rect)
591{
592    struct {
593        int xy[2];
594        int wh[2];
595    } crop, win;
596    struct {
597        int lt[2];
598        int rb[2];
599    } vis;
600    win.xy[0] = cfg->win.x; win.xy[1] = cfg->win.y;
601    win.wh[0] = cfg->win.w; win.wh[1] = cfg->win.h;
602    crop.xy[0] = cfg->crop.x; crop.xy[1] = cfg->crop.y;
603    crop.wh[0] = cfg->crop.w; crop.wh[1] = cfg->crop.h;
604    vis.lt[0] = vis_rect.left; vis.lt[1] = vis_rect.top;
605    vis.rb[0] = vis_rect.right; vis.rb[1] = vis_rect.bottom;
606
607    int c, swap = cfg->rotation & 1;
608
609    /* align crop window with display coordinates */
610    if (swap)
611        crop.xy[1] -= (crop.wh[1] = -crop.wh[1]);
612    if (cfg->rotation & 2)
613        crop.xy[!swap] -= (crop.wh[!swap] = -crop.wh[!swap]);
614    if ((!cfg->mirror) ^ !(cfg->rotation & 2))
615        crop.xy[swap] -= (crop.wh[swap] = -crop.wh[swap]);
616
617    for (c = 0; c < 2; c++) {
618        /* see if complete buffer is outside the vis or it is
619          fully cropped or scaled to 0 */
620        if (win.wh[c] <= 0 || vis.rb[c] <= vis.lt[c] ||
621            win.xy[c] + win.wh[c] <= vis.lt[c] ||
622            win.xy[c] >= vis.rb[c] ||
623            !crop.wh[c ^ swap])
624            return -ENOENT;
625
626        /* crop left/top */
627        if (win.xy[c] < vis.lt[c]) {
628            /* correction term */
629            int a = (vis.lt[c] - win.xy[c]) * crop.wh[c ^ swap] / win.wh[c];
630            crop.xy[c ^ swap] += a;
631            crop.wh[c ^ swap] -= a;
632            win.wh[c] -= vis.lt[c] - win.xy[c];
633            win.xy[c] = vis.lt[c];
634        }
635        /* crop right/bottom */
636        if (win.xy[c] + win.wh[c] > vis.rb[c]) {
637            crop.wh[c ^ swap] = crop.wh[c ^ swap] * (vis.rb[c] - win.xy[c]) / win.wh[c];
638            win.wh[c] = vis.rb[c] - win.xy[c];
639        }
640
641        if (!crop.wh[c ^ swap] || !win.wh[c])
642            return -ENOENT;
643    }
644
645    /* realign crop window to buffer coordinates */
646    if (cfg->rotation & 2)
647        crop.xy[!swap] -= (crop.wh[!swap] = -crop.wh[!swap]);
648    if ((!cfg->mirror) ^ !(cfg->rotation & 2))
649        crop.xy[swap] -= (crop.wh[swap] = -crop.wh[swap]);
650    if (swap)
651        crop.xy[1] -= (crop.wh[1] = -crop.wh[1]);
652
653    cfg->win.x = win.xy[0]; cfg->win.y = win.xy[1];
654    cfg->win.w = win.wh[0]; cfg->win.h = win.wh[1];
655    cfg->crop.x = crop.xy[0]; cfg->crop.y = crop.xy[1];
656    cfg->crop.w = crop.wh[0]; cfg->crop.h = crop.wh[1];
657
658    return 0;
659}
660
661static void
662omap4_hwc_adjust_ext_layer(omap4_hwc_ext_t *ext, struct dss2_ovl_info *ovl)
663{
664    struct dss2_ovl_cfg *oc = &ovl->cfg;
665    float x, y, w, h;
666
667    /* crop to clone region if mirroring */
668    if (!ext->current.docking &&
669        crop_to_rect(&ovl->cfg, ext->mirror_region) != 0) {
670        ovl->cfg.enabled = 0;
671        return;
672    }
673
674    /* display position */
675    x = ext->m[0][0] * oc->win.x + ext->m[0][1] * oc->win.y + ext->m[0][2];
676    y = ext->m[1][0] * oc->win.x + ext->m[1][1] * oc->win.y + ext->m[1][2];
677    w = ext->m[0][0] * oc->win.w + ext->m[0][1] * oc->win.h;
678    h = ext->m[1][0] * oc->win.w + ext->m[1][1] * oc->win.h;
679    oc->win.x = m_round(w > 0 ? x : x + w);
680    oc->win.y = m_round(h > 0 ? y : y + h);
681    oc->win.w = m_round(w > 0 ? w : -w);
682    oc->win.h = m_round(h > 0 ? h : -h);
683
684    /* combining transformations: F^a*R^b*F^i*R^j = F^(a+b)*R^(j+b*(-1)^i), because F*R = R^(-1)*F */
685    oc->rotation += (oc->mirror ? -1 : 1) * ext->current.rotation;
686    oc->rotation &= 3;
687    if (ext->current.hflip)
688        oc->mirror = !oc->mirror;
689}
690
691static struct dsscomp_dispc_limitations {
692    __u8 max_xdecim_2d;
693    __u8 max_ydecim_2d;
694    __u8 max_xdecim_1d;
695    __u8 max_ydecim_1d;
696    __u32 fclk;
697    __u8 max_downscale;
698    __u8 min_width;
699    __u16 integer_scale_ratio_limit;
700    __u16 max_width;
701    __u16 max_height;
702} limits = {
703    .max_xdecim_1d = 16,
704    .max_xdecim_2d = 16,
705    .max_ydecim_1d = 16,
706    .max_ydecim_2d = 2,
707    .fclk = 170666666,
708    .max_downscale = 4,
709    .min_width = 2,
710    .integer_scale_ratio_limit = 2048,
711    .max_width = 2048,
712    .max_height = 2048,
713};
714
715static int omap4_hwc_can_scale(__u32 src_w, __u32 src_h, __u32 dst_w, __u32 dst_h, int is_2d,
716                               struct dsscomp_display_info *dis, struct dsscomp_dispc_limitations *limits,
717                               __u32 pclk)
718{
719    __u32 fclk = limits->fclk / 1000;
720
721    /* ERRATAs */
722    /* cannot render 1-width layers on DSI video mode panels - we just disallow all 1-width LCD layers */
723    if (dis->channel != OMAP_DSS_CHANNEL_DIGIT && dst_w < limits->min_width)
724        return 0;
725
726    /* NOTE: no support for checking YUV422 layers that are tricky to scale */
727
728    /* max downscale */
729    if (dst_h < src_h / limits->max_downscale / (is_2d ? limits->max_ydecim_2d : limits->max_ydecim_1d))
730        return 0;
731
732    /* for manual panels pclk is 0, and there are no pclk based scaling limits */
733    if (!pclk)
734        return (dst_w < src_w / limits->max_downscale / (is_2d ? limits->max_xdecim_2d : limits->max_xdecim_1d));
735
736    /* :HACK: limit horizontal downscale well below theoretical limit as we saw display artifacts */
737    if (dst_w < src_w / 4)
738        return 0;
739
740    /* max horizontal downscale is 4, or the fclk/pixclk */
741    if (fclk > pclk * limits->max_downscale)
742        fclk = pclk * limits->max_downscale;
743    /* for small parts, we need to use integer fclk/pixclk */
744    if (src_w < limits->integer_scale_ratio_limit)
745        fclk = fclk / pclk * pclk;
746    if ((__u32) dst_w < src_w * pclk / fclk / (is_2d ? limits->max_xdecim_2d : limits->max_xdecim_1d))
747        return 0;
748
749    return 1;
750}
751
752static int omap4_hwc_can_scale_layer(omap4_hwc_device_t *hwc_dev, hwc_layer_t *layer, IMG_native_handle_t *handle)
753{
754    int src_w = WIDTH(layer->sourceCrop);
755    int src_h = HEIGHT(layer->sourceCrop);
756    int dst_w = WIDTH(layer->displayFrame);
757    int dst_h = HEIGHT(layer->displayFrame);
758
759    /* account for 90-degree rotation */
760    if (layer->transform & HWC_TRANSFORM_ROT_90)
761        swap(src_w, src_h);
762
763    /* NOTE: layers should be able to be scaled externally since
764       framebuffer is able to be scaled on selected external resolution */
765    return omap4_hwc_can_scale(src_w, src_h, dst_w, dst_h, is_NV12(handle), &hwc_dev->fb_dis, &limits,
766                               hwc_dev->fb_dis.timings.pixel_clock);
767}
768
769static int omap4_hwc_is_valid_layer(omap4_hwc_device_t *hwc_dev,
770                                    hwc_layer_t *layer,
771                                    IMG_native_handle_t *handle)
772{
773    /* Skip layers are handled by SF */
774    if ((layer->flags & HWC_SKIP_LAYER) || !handle)
775        return 0;
776
777    if (!omap4_hwc_is_valid_format(handle->iFormat))
778        return 0;
779
780    /* 1D buffers: no transform, must fit in TILER slot */
781    if (!is_NV12(handle)) {
782        if (layer->transform)
783            return 0;
784        if (mem1d(handle) > MAX_TILER_SLOT)
785            return 0;
786    }
787
788    return omap4_hwc_can_scale_layer(hwc_dev, layer, handle);
789}
790
791static __u32 add_scaling_score(__u32 score,
792                               __u32 xres, __u32 yres, __u32 refresh,
793                               __u32 ext_xres, __u32 ext_yres,
794                               __u32 mode_xres, __u32 mode_yres, __u32 mode_refresh)
795{
796    __u32 area = xres * yres;
797    __u32 ext_area = ext_xres * ext_yres;
798    __u32 mode_area = mode_xres * mode_yres;
799
800    /* prefer to upscale (1% tolerance) [0..1] (insert after 1st bit) */
801    int upscale = (ext_xres >= xres * 99 / 100 && ext_yres >= yres * 99 / 100);
802    score = (((score & ~1) | upscale) << 1) | (score & 1);
803
804    /* pick minimum scaling [0..16] */
805    if (ext_area > area)
806        score = (score << 5) | (16 * area / ext_area);
807    else
808        score = (score << 5) | (16 * ext_area / area);
809
810    /* pick smallest leftover area [0..16] */
811    score = (score << 5) | ((16 * ext_area + (mode_area >> 1)) / mode_area);
812
813    /* adjust mode refresh rate */
814    mode_refresh += mode_refresh % 6 == 5;
815
816    /* prefer same or higher frame rate */
817    upscale = (mode_refresh >= refresh);
818    score = (score << 1) | upscale;
819
820    /* pick closest frame rate */
821    if (mode_refresh > refresh)
822        score = (score << 8) | (240 * refresh / mode_refresh);
823    else
824        score = (score << 8) | (240 * mode_refresh / refresh);
825
826    return score;
827}
828
829static int omap4_hwc_set_best_hdmi_mode(omap4_hwc_device_t *hwc_dev, __u32 xres, __u32 yres,
830                                        float xpy)
831{
832    struct _qdis {
833        struct dsscomp_display_info dis;
834        struct dsscomp_videomode modedb[16];
835    } d = { .dis = { .ix = 1 } };
836    omap4_hwc_ext_t *ext = &hwc_dev->ext;
837
838    d.dis.modedb_len = sizeof(d.modedb) / sizeof(*d.modedb);
839    int ret = ioctl(hwc_dev->dsscomp_fd, DSSCIOC_QUERY_DISPLAY, &d);
840    if (ret)
841        return ret;
842
843    if (d.dis.timings.x_res * d.dis.timings.y_res == 0 ||
844        xres * yres == 0)
845        return -EINVAL;
846
847    __u32 i, best = ~0, best_score = 0;
848    ext->width = d.dis.width_in_mm;
849    ext->height = d.dis.height_in_mm;
850    ext->xres = d.dis.timings.x_res;
851    ext->yres = d.dis.timings.y_res;
852
853    /* use VGA external resolution as default */
854    if (!ext->xres || !ext->yres) {
855        ext->xres = 640;
856        ext->yres = 480;
857    }
858
859    __u32 ext_fb_xres, ext_fb_yres;
860    for (i = 0; i < d.dis.modedb_len; i++) {
861        __u32 score = 0;
862        __u32 mode_xres = d.modedb[i].xres;
863        __u32 mode_yres = d.modedb[i].yres;
864        __u32 ext_width = d.dis.width_in_mm;
865        __u32 ext_height = d.dis.height_in_mm;
866
867        if (d.modedb[i].flag & FB_FLAG_RATIO_4_3) {
868            ext_width = 4;
869            ext_height = 3;
870        } else if (d.modedb[i].flag & FB_FLAG_RATIO_16_9) {
871            ext_width = 16;
872            ext_height = 9;
873        }
874
875        if (!mode_xres || !mode_yres)
876            continue;
877
878        get_max_dimensions(xres, yres, xpy, mode_xres, mode_yres,
879                           ext_width, ext_height, &ext_fb_xres, &ext_fb_yres);
880
881        /* we need to ensure that even TILER2D buffers can be scaled */
882        if (!d.modedb[i].pixclock ||
883            d.modedb[i].vmode ||
884            !omap4_hwc_can_scale(xres, yres, ext_fb_xres, ext_fb_yres,
885                                 1, &d.dis, &limits,
886                                 1000000000 / d.modedb[i].pixclock))
887            continue;
888
889        /* prefer CEA modes */
890        if (d.modedb[i].flag & (FB_FLAG_RATIO_4_3 | FB_FLAG_RATIO_16_9))
891            score = 1;
892
893        /* prefer the same mode as we use for mirroring to avoid mode change */
894       score = (score << 1) | (i == ~ext->mirror_mode && ext->avoid_mode_change);
895
896        score = add_scaling_score(score, xres, yres, 60, ext_fb_xres, ext_fb_yres,
897                                  mode_xres, mode_yres, d.modedb[i].refresh ? : 1);
898
899        LOGD("#%d: %dx%d %dHz", i, mode_xres, mode_yres, d.modedb[i].refresh);
900        if (debug)
901            LOGD("  score=0x%x adj.res=%dx%d", score, ext_fb_xres, ext_fb_yres);
902        if (best_score < score) {
903            ext->width = ext_width;
904            ext->height = ext_height;
905            ext->xres = mode_xres;
906            ext->yres = mode_yres;
907            best = i;
908            best_score = score;
909        }
910    }
911    if (~best) {
912        struct dsscomp_setup_display_data sdis = { .ix = 1, };
913        sdis.mode = d.dis.modedb[best];
914        LOGD("picking #%d", best);
915        /* only reconfigure on change */
916        if (ext->last_mode != ~best)
917            ioctl(hwc_dev->dsscomp_fd, DSSCIOC_SETUP_DISPLAY, &sdis);
918        ext->last_mode = ~best;
919    } else {
920        __u32 ext_width = d.dis.width_in_mm;
921        __u32 ext_height = d.dis.height_in_mm;
922        __u32 ext_fb_xres, ext_fb_yres;
923
924        get_max_dimensions(xres, yres, xpy, d.dis.timings.x_res, d.dis.timings.y_res,
925                           ext_width, ext_height, &ext_fb_xres, &ext_fb_yres);
926        if (!d.dis.timings.pixel_clock ||
927            d.dis.mgr.interlaced ||
928            !omap4_hwc_can_scale(xres, yres, ext_fb_xres, ext_fb_yres,
929                                 1, &d.dis, &limits,
930                                 d.dis.timings.pixel_clock)) {
931            LOGW("DSS scaler cannot support HDMI cloning");
932            return -1;
933        }
934    }
935    ext->last_xres_used = xres;
936    ext->last_yres_used = yres;
937    ext->last_xpy = xpy;
938    if (d.dis.channel == OMAP_DSS_CHANNEL_DIGIT)
939        ext->on_tv = 1;
940    return 0;
941}
942
943struct counts {
944    unsigned int possible_overlay_layers;
945    unsigned int composited_layers;
946    unsigned int scaled_layers;
947    unsigned int RGB;
948    unsigned int BGR;
949    unsigned int NV12;
950    unsigned int dockable;
951    unsigned int protected;
952
953    unsigned int max_hw_overlays;
954    unsigned int max_scaling_overlays;
955    unsigned int mem;
956};
957
958static void gather_layer_statistics(omap4_hwc_device_t *hwc_dev, struct counts *num, hwc_layer_list_t *list)
959{
960    unsigned int i;
961
962    /* Figure out how many layers we can support via DSS */
963    for (i = 0; list && i < list->numHwLayers; i++) {
964        hwc_layer_t *layer = &list->hwLayers[i];
965        IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
966
967        layer->compositionType = HWC_FRAMEBUFFER;
968
969        if (omap4_hwc_is_valid_layer(hwc_dev, layer, handle)) {
970            num->possible_overlay_layers++;
971
972            /* NV12 layers can only be rendered on scaling overlays */
973            if (scaled(layer) || is_NV12(handle))
974                num->scaled_layers++;
975
976            if (is_BGR(handle))
977                num->BGR++;
978            else if (is_RGB(handle))
979                num->RGB++;
980            else if (is_NV12(handle))
981                num->NV12++;
982
983            if (dockable(layer))
984                num->dockable++;
985
986            if (is_protected(layer))
987                num->protected++;
988
989            num->mem += mem1d(handle);
990        }
991    }
992}
993
994static void decide_supported_cloning(omap4_hwc_device_t *hwc_dev, struct counts *num)
995{
996    omap4_hwc_ext_t *ext = &hwc_dev->ext;
997    int nonscaling_ovls = NUM_NONSCALING_OVERLAYS;
998    num->max_hw_overlays = MAX_HW_OVERLAYS;
999
1000    /*
1001     * We cannot atomically switch overlays from one display to another.  First, they
1002     * have to be disabled, and the disabling has to take effect on the current display.
1003     * We keep track of the available number of overlays here.
1004     */
1005    if (ext->dock.enabled && !(ext->mirror.enabled && !(num->dockable || ext->force_dock))) {
1006        /* some overlays may already be used by the external display, so we account for this */
1007
1008        /* reserve just a video pipeline for HDMI if docking */
1009        hwc_dev->ext_ovls = (num->dockable || ext->force_dock) ? 1 : 0;
1010        num->max_hw_overlays -= max(hwc_dev->ext_ovls, hwc_dev->last_ext_ovls);
1011
1012        /* use mirroring transform if we are auto-switching to docking mode while mirroring*/
1013        if (ext->mirror.enabled) {
1014            ext->current = ext->mirror;
1015            ext->current.docking = 1;
1016        } else {
1017            ext->current = ext->dock;
1018        }
1019    } else if (ext->mirror.enabled) {
1020        /*
1021         * otherwise, manage just from half the pipelines.  NOTE: there is
1022         * no danger of having used too many overlays for external display here.
1023         */
1024        num->max_hw_overlays >>= 1;
1025        nonscaling_ovls >>= 1;
1026        hwc_dev->ext_ovls = MAX_HW_OVERLAYS - num->max_hw_overlays;
1027        ext->current = ext->mirror;
1028    } else {
1029        num->max_hw_overlays -= hwc_dev->last_ext_ovls;
1030        hwc_dev->ext_ovls = 0;
1031        ext->current.enabled = 0;
1032    }
1033
1034    /*
1035     * :TRICKY: We may not have enough overlays on the external display.  We "reserve" them
1036     * here to figure out if mirroring is supported, but may not do mirroring for the first
1037     * frame while the overlays required for it are cleared.
1038     */
1039    hwc_dev->ext_ovls_wanted = hwc_dev->ext_ovls;
1040    hwc_dev->ext_ovls = min(MAX_HW_OVERLAYS - hwc_dev->last_int_ovls, hwc_dev->ext_ovls);
1041
1042    /* if mirroring, we are limited by both internal and external overlays.  However,
1043       ext_ovls is always <= MAX_HW_OVERLAYS / 2 <= max_hw_overlays */
1044    if (hwc_dev->ext_ovls && ext->current.enabled && !ext->current.docking)
1045        num->max_hw_overlays = hwc_dev->ext_ovls;
1046
1047    num->max_scaling_overlays = num->max_hw_overlays - nonscaling_ovls;
1048}
1049
1050static int can_dss_render_all(omap4_hwc_device_t *hwc_dev, struct counts *num)
1051{
1052    omap4_hwc_ext_t *ext = &hwc_dev->ext;
1053    int on_tv = ext->on_tv && ext->current.enabled;
1054    int tform = ext->current.enabled && (ext->current.rotation || ext->current.hflip);
1055
1056    return  !hwc_dev->force_sgx &&
1057            /* must have at least one layer if using composition bypass to get sync object */
1058            num->possible_overlay_layers &&
1059            num->possible_overlay_layers <= num->max_hw_overlays &&
1060            num->possible_overlay_layers == num->composited_layers &&
1061            num->scaled_layers <= num->max_scaling_overlays &&
1062            num->NV12 <= num->max_scaling_overlays &&
1063            /* fits into TILER slot */
1064            num->mem <= MAX_TILER_SLOT &&
1065            /* we cannot clone non-NV12 transformed layers */
1066            (!tform || num->NV12 == num->possible_overlay_layers) &&
1067            /* HDMI cannot display BGR */
1068            (num->BGR == 0 || (num->RGB == 0 && !on_tv) || !hwc_dev->flags_rgb_order);
1069}
1070
1071static inline int can_dss_render_layer(omap4_hwc_device_t *hwc_dev,
1072            hwc_layer_t *layer)
1073{
1074    IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
1075
1076    omap4_hwc_ext_t *ext = &hwc_dev->ext;
1077    int on_tv = ext->on_tv && ext->current.enabled;
1078    int tform = ext->current.enabled && (ext->current.rotation || ext->current.hflip);
1079
1080    return omap4_hwc_is_valid_layer(hwc_dev, layer, handle) &&
1081           /* cannot rotate non-NV12 layers on external display */
1082           (!tform || is_NV12(handle)) &&
1083           /* skip non-NV12 layers if also using SGX (if nv12_only flag is set) */
1084           (!hwc_dev->flags_nv12_only || (!hwc_dev->use_sgx || is_NV12(handle))) &&
1085           /* make sure RGB ordering is consistent (if rgb_order flag is set) */
1086           (!(hwc_dev->swap_rb ? is_RGB(handle) : is_BGR(handle)) ||
1087            !hwc_dev->flags_rgb_order) &&
1088           /* TV can only render RGB */
1089           !(on_tv && is_BGR(handle));
1090}
1091
1092static inline int display_area(struct dss2_ovl_info *o)
1093{
1094    return o->cfg.win.w * o->cfg.win.h;
1095}
1096
1097static int clone_layer(omap4_hwc_device_t *hwc_dev, int ix) {
1098    struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->dsscomp_data;
1099    omap4_hwc_ext_t *ext = &hwc_dev->ext;
1100    int ext_ovl_ix = dsscomp->num_ovls - hwc_dev->post2_layers;
1101    struct dss2_ovl_info *o = &dsscomp->ovls[dsscomp->num_ovls];
1102
1103    if (dsscomp->num_ovls >= MAX_HW_OVERLAYS) {
1104        LOGE("**** cannot clone layer #%d. using all %d overlays.", ix, dsscomp->num_ovls);
1105        return -EBUSY;
1106    }
1107
1108    memcpy(o, dsscomp->ovls + ix, sizeof(*o));
1109
1110    /* reserve overlays at end for other display */
1111    o->cfg.ix = MAX_HW_OVERLAYS - 1 - ext_ovl_ix;
1112    o->cfg.mgr_ix = 1;
1113    o->addressing = OMAP_DSS_BUFADDR_OVL_IX;
1114    o->ba = ix;
1115
1116    /* use distinct z values (to simplify z-order checking) */
1117    o->cfg.zorder += hwc_dev->post2_layers;
1118
1119    omap4_hwc_adjust_ext_layer(&hwc_dev->ext, o);
1120    dsscomp->num_ovls++;
1121    return 0;
1122}
1123
1124static int clone_external_layer(omap4_hwc_device_t *hwc_dev, int ix) {
1125    struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->dsscomp_data;
1126    omap4_hwc_ext_t *ext = &hwc_dev->ext;
1127
1128    /* mirror only 1 external layer */
1129    struct dss2_ovl_info *o = &dsscomp->ovls[ix];
1130
1131    /* full screen video after transformation */
1132    __u32 xres = o->cfg.crop.w, yres = o->cfg.crop.h;
1133    if ((ext->current.rotation + o->cfg.rotation) & 1)
1134        swap(xres, yres);
1135    float xpy = ext->lcd_xpy * o->cfg.win.w / o->cfg.win.h;
1136    if (o->cfg.rotation & 1)
1137        xpy = o->cfg.crop.h / xpy / o->cfg.crop.w;
1138    else
1139        xpy = o->cfg.crop.h * xpy / o->cfg.crop.w;
1140    if (ext->current.rotation & 1)
1141        xpy = 1. / xpy;
1142
1143    /* adjust hdmi mode based on resolution */
1144    if (xres != ext->last_xres_used ||
1145        yres != ext->last_yres_used ||
1146        xpy < ext->last_xpy * (1.f - ASPECT_RATIO_TOLERANCE) ||
1147        xpy * (1.f - ASPECT_RATIO_TOLERANCE) > ext->last_xpy) {
1148        LOGD("set up HDMI for %d*%d\n", xres, yres);
1149        if (omap4_hwc_set_best_hdmi_mode(hwc_dev, xres, yres, xpy)) {
1150            ext->current.enabled = 0;
1151            return -ENODEV;
1152        }
1153    }
1154
1155    struct hwc_rect region = {
1156        .left = o->cfg.win.x, .top = o->cfg.win.y,
1157        .right = o->cfg.win.x + o->cfg.win.w,
1158        .bottom = o->cfg.win.y + o->cfg.win.h
1159    };
1160    set_ext_matrix(&hwc_dev->ext, region);
1161
1162    return clone_layer(hwc_dev, ix);
1163}
1164
1165static int setup_mirroring(omap4_hwc_device_t *hwc_dev)
1166{
1167    omap4_hwc_ext_t *ext = &hwc_dev->ext;
1168
1169    __u32 xres = WIDTH(ext->mirror_region);
1170    __u32 yres = HEIGHT(ext->mirror_region);
1171    if (ext->current.rotation & 1)
1172       swap(xres, yres);
1173    if (omap4_hwc_set_best_hdmi_mode(hwc_dev, xres, yres, ext->lcd_xpy))
1174        return -ENODEV;
1175    set_ext_matrix(ext, ext->mirror_region);
1176    return 0;
1177}
1178
1179static int omap4_hwc_prepare(struct hwc_composer_device *dev, hwc_layer_list_t* list)
1180{
1181    omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev;
1182    struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->dsscomp_data;
1183    struct counts num = { .composited_layers = list ? list->numHwLayers : 0 };
1184    unsigned int i, ix;
1185
1186    pthread_mutex_lock(&hwc_dev->lock);
1187    memset(dsscomp, 0x0, sizeof(*dsscomp));
1188    dsscomp->sync_id = sync_id++;
1189
1190    gather_layer_statistics(hwc_dev, &num, list);
1191
1192    decide_supported_cloning(hwc_dev, &num);
1193
1194    /* Disable the forced SGX rendering if there is only one layer */
1195    if (hwc_dev->force_sgx && num.composited_layers <= 1)
1196        hwc_dev->force_sgx = 0;
1197
1198    /* phase 3 logic */
1199    if (can_dss_render_all(hwc_dev, &num)) {
1200        /* All layers can be handled by the DSS -- don't use SGX for composition */
1201        hwc_dev->use_sgx = 0;
1202        hwc_dev->swap_rb = num.BGR != 0;
1203    } else {
1204        /* Use SGX for composition plus first 3 layers that are DSS renderable */
1205        hwc_dev->use_sgx = 1;
1206        hwc_dev->swap_rb = is_BGR_format(hwc_dev->fb_dev->base.format);
1207    }
1208
1209    /* setup pipes */
1210    dsscomp->num_ovls = hwc_dev->use_sgx;
1211    int z = 0;
1212    int fb_z = -1;
1213    int scaled_gfx = 0;
1214    int ix_docking = -1;
1215
1216    /* set up if DSS layers */
1217    unsigned int mem_used = 0;
1218    hwc_dev->ovls_blending = 0;
1219    for (i = 0; list && i < list->numHwLayers; i++) {
1220        hwc_layer_t *layer = &list->hwLayers[i];
1221        IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
1222
1223        if (dsscomp->num_ovls < num.max_hw_overlays &&
1224            can_dss_render_layer(hwc_dev, layer) &&
1225            (!hwc_dev->force_sgx ||
1226             /* render protected and dockable layers via DSS */
1227             is_protected(layer) ||
1228             (hwc_dev->ext.current.docking && hwc_dev->ext.current.enabled && dockable(layer))) &&
1229            mem_used + mem1d(handle) < MAX_TILER_SLOT &&
1230            /* can't have a transparent overlay in the middle of the framebuffer stack */
1231            !(is_BLENDED(layer) && fb_z >= 0)) {
1232
1233            /* render via DSS overlay */
1234            mem_used += mem1d(handle);
1235            layer->compositionType = HWC_OVERLAY;
1236
1237            /* clear FB above all opaque layers if rendering via SGX */
1238            if (hwc_dev->use_sgx && !is_BLENDED(layer))
1239                layer->hints |= HWC_HINT_CLEAR_FB;
1240            /* see if any of the (non-backmost) overlays are doing blending */
1241            else if (is_BLENDED(layer) && i > 0)
1242                hwc_dev->ovls_blending = 1;
1243
1244            hwc_dev->buffers[dsscomp->num_ovls] = layer->handle;
1245
1246            omap4_hwc_setup_layer(hwc_dev,
1247                                  &dsscomp->ovls[dsscomp->num_ovls],
1248                                  layer,
1249                                  z,
1250                                  handle->iFormat,
1251                                  handle->iWidth,
1252                                  handle->iHeight);
1253
1254            dsscomp->ovls[dsscomp->num_ovls].cfg.ix = dsscomp->num_ovls;
1255            dsscomp->ovls[dsscomp->num_ovls].addressing = OMAP_DSS_BUFADDR_LAYER_IX;
1256            dsscomp->ovls[dsscomp->num_ovls].ba = dsscomp->num_ovls;
1257
1258            /* ensure GFX layer is never scaled */
1259            if (dsscomp->num_ovls == 0) {
1260                scaled_gfx = scaled(layer) || is_NV12(handle);
1261            } else if (scaled_gfx && !scaled(layer) && !is_NV12(handle)) {
1262                /* swap GFX layer with this one */
1263                dsscomp->ovls[dsscomp->num_ovls].cfg.ix = 0;
1264                dsscomp->ovls[0].cfg.ix = dsscomp->num_ovls;
1265                scaled_gfx = 0;
1266            }
1267
1268            /* remember largest dockable layer */
1269            if (dockable(layer) &&
1270                (ix_docking < 0 ||
1271                 display_area(&dsscomp->ovls[dsscomp->num_ovls]) > display_area(&dsscomp->ovls[ix_docking])))
1272                ix_docking = dsscomp->num_ovls;
1273
1274            dsscomp->num_ovls++;
1275            z++;
1276        } else if (hwc_dev->use_sgx) {
1277            if (fb_z < 0) {
1278                /* NOTE: we are not handling transparent cutout for now */
1279                fb_z = z;
1280                z++;
1281            } else {
1282                /* move fb z-order up (by lowering dss layers) */
1283                while (fb_z < z - 1)
1284                    dsscomp->ovls[1 + fb_z++].cfg.zorder--;
1285            }
1286        }
1287    }
1288
1289    /* if scaling GFX (e.g. only 1 scaled surface) use a VID pipe */
1290    if (scaled_gfx)
1291        dsscomp->ovls[0].cfg.ix = dsscomp->num_ovls;
1292
1293    if (hwc_dev->use_sgx) {
1294        /* assign a z-layer for fb */
1295        if (fb_z < 0) {
1296            if (num.composited_layers)
1297                LOGE("**** should have assigned z-layer for fb");
1298            fb_z = z++;
1299        }
1300
1301        hwc_dev->buffers[0] = NULL;
1302        omap4_hwc_setup_layer_base(&dsscomp->ovls[0].cfg, fb_z,
1303                                   hwc_dev->fb_dev->base.format,
1304                                   1,   /* FB is always premultiplied */
1305                                   hwc_dev->fb_dev->base.width,
1306                                   hwc_dev->fb_dev->base.height);
1307        dsscomp->ovls[0].cfg.pre_mult_alpha = 1;
1308        dsscomp->ovls[0].addressing = OMAP_DSS_BUFADDR_LAYER_IX;
1309        dsscomp->ovls[0].ba = 0;
1310    }
1311
1312    /* mirror layers */
1313    hwc_dev->post2_layers = dsscomp->num_ovls;
1314
1315    omap4_hwc_ext_t *ext = &hwc_dev->ext;
1316    if (ext->current.enabled && hwc_dev->ext_ovls) {
1317        if (ext->current.docking && ix_docking >= 0) {
1318            if (clone_external_layer(hwc_dev, ix_docking) == 0)
1319                dsscomp->ovls[dsscomp->num_ovls - 1].cfg.zorder = z++;
1320        } else if (ext->current.docking && ix_docking < 0 && ext->force_dock) {
1321            ix_docking = dsscomp->num_ovls;
1322            struct dss2_ovl_info *oi = &dsscomp->ovls[ix_docking];
1323            omap4_hwc_setup_layer_base(&oi->cfg, 0, HAL_PIXEL_FORMAT_BGRA_8888, 1,
1324                                       dock_image.width, dock_image.height);
1325            oi->cfg.stride = dock_image.rowbytes;
1326            if (clone_external_layer(hwc_dev, ix_docking) == 0) {
1327                oi->addressing = OMAP_DSS_BUFADDR_FB;
1328                oi->ba = 0;
1329                z++;
1330            }
1331        } else if (!ext->current.docking) {
1332            int res = 0;
1333
1334            /* reset mode if we are coming from docking */
1335            if (ext->last.docking)
1336                res = setup_mirroring(hwc_dev);
1337
1338            /* mirror all layers */
1339            for (ix = 0; res == 0 && ix < hwc_dev->post2_layers; ix++) {
1340                if (clone_layer(hwc_dev, ix))
1341                    break;
1342                z++;
1343            }
1344        }
1345    }
1346    ext->last = ext->current;
1347
1348    if (z != dsscomp->num_ovls || dsscomp->num_ovls > MAX_HW_OVERLAYS)
1349        LOGE("**** used %d z-layers for %d overlays\n", z, dsscomp->num_ovls);
1350
1351    /* verify all z-orders and overlay indices are distinct */
1352    for (i = z = ix = 0; i < dsscomp->num_ovls; i++) {
1353        struct dss2_ovl_cfg *c = &dsscomp->ovls[i].cfg;
1354
1355        if (z & (1 << c->zorder))
1356            LOGE("**** used z-order #%d multiple times", c->zorder);
1357        if (ix & (1 << c->ix))
1358            LOGE("**** used ovl index #%d multiple times", c->ix);
1359        z |= 1 << c->zorder;
1360        ix |= 1 << c->ix;
1361    }
1362    dsscomp->mode = DSSCOMP_SETUP_DISPLAY;
1363    dsscomp->mgrs[0].ix = 0;
1364    dsscomp->mgrs[0].alpha_blending = 1;
1365    dsscomp->mgrs[0].swap_rb = hwc_dev->swap_rb;
1366    dsscomp->num_mgrs = 1;
1367
1368    if (ext->current.enabled || hwc_dev->last_ext_ovls) {
1369        dsscomp->mgrs[1] = dsscomp->mgrs[0];
1370        dsscomp->mgrs[1].ix = 1;
1371        dsscomp->num_mgrs++;
1372        hwc_dev->ext_ovls = dsscomp->num_ovls - hwc_dev->post2_layers;
1373    }
1374
1375    if (debug) {
1376        LOGD("prepare (%d) - %s (comp=%d, poss=%d/%d scaled, RGB=%d,BGR=%d,NV12=%d) (ext=%s%s%ddeg%s %dex/%dmx (last %dex,%din)\n",
1377             dsscomp->sync_id,
1378             hwc_dev->use_sgx ? "SGX+OVL" : "all-OVL",
1379             num.composited_layers,
1380             num.possible_overlay_layers, num.scaled_layers,
1381             num.RGB, num.BGR, num.NV12,
1382             ext->on_tv ? "tv+" : "",
1383             ext->current.enabled ? ext->current.docking ? "dock+" : "mirror+" : "OFF+",
1384             ext->current.rotation * 90,
1385             ext->current.hflip ? "+hflip" : "",
1386             hwc_dev->ext_ovls, num.max_hw_overlays, hwc_dev->last_ext_ovls, hwc_dev->last_int_ovls);
1387    }
1388
1389    pthread_mutex_unlock(&hwc_dev->lock);
1390    return 0;
1391}
1392
1393static void omap4_hwc_reset_screen(omap4_hwc_device_t *hwc_dev)
1394{
1395    static int first_set = 1;
1396    int ret;
1397
1398    if (first_set) {
1399        first_set = 0;
1400        struct dsscomp_setup_dispc_data d = {
1401            .num_mgrs = 1,
1402        };
1403        /* remove bootloader image from the screen as blank/unblank does not change the composition */
1404        ret = ioctl(hwc_dev->dsscomp_fd, DSSCIOC_SETUP_DISPC, &d);
1405        if (ret)
1406            LOGW("failed to remove bootloader image");
1407
1408        /* blank and unblank fd to make sure display is properly programmed on boot.
1409         * This is needed because the bootloader can not be trusted.
1410         */
1411        ret = ioctl(hwc_dev->fb_fd, FBIOBLANK, FB_BLANK_POWERDOWN);
1412        if (ret)
1413            LOGW("failed to blank display");
1414
1415        ret = ioctl(hwc_dev->fb_fd, FBIOBLANK, FB_BLANK_UNBLANK);
1416        if (ret)
1417            LOGW("failed to blank display");
1418    }
1419}
1420
1421static int omap4_hwc_set(struct hwc_composer_device *dev, hwc_display_t dpy,
1422               hwc_surface_t sur, hwc_layer_list_t* list)
1423{
1424    omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev;
1425    struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->dsscomp_data;
1426    int err = 0;
1427    int invalidate;
1428
1429    pthread_mutex_lock(&hwc_dev->lock);
1430
1431    omap4_hwc_reset_screen(hwc_dev);
1432
1433    invalidate = hwc_dev->ext_ovls_wanted && !hwc_dev->ext_ovls;
1434
1435    if (debug)
1436        dump_set_info(hwc_dev, list);
1437
1438    if (dpy && sur) {
1439        // list can be NULL which means hwc is temporarily disabled.
1440        // however, if dpy and sur are null it means we're turning the
1441        // screen off. no shall not call eglSwapBuffers() in that case.
1442
1443        if (hwc_dev->use_sgx) {
1444            if (!eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur)) {
1445                LOGE("eglSwapBuffers error");
1446                err = HWC_EGL_ERROR;
1447                goto err_out;
1448            }
1449        }
1450
1451        //dump_dsscomp(dsscomp);
1452
1453        // signal the event thread that a post has happened
1454        write(hwc_dev->pipe_fds[1], "s", 1);
1455        if (hwc_dev->force_sgx > 0)
1456            hwc_dev->force_sgx--;
1457
1458        err = hwc_dev->fb_dev->Post2((framebuffer_device_t *)hwc_dev->fb_dev,
1459                                 hwc_dev->buffers,
1460                                 hwc_dev->post2_layers,
1461                                 dsscomp, sizeof(*dsscomp));
1462
1463        if (!hwc_dev->use_sgx) {
1464            __u32 crt = 0;
1465            int err2 = ioctl(hwc_dev->fb_fd, FBIO_WAITFORVSYNC, &crt);
1466            if (err2) {
1467                LOGE("failed to wait for vsync (%d)", errno);
1468                err = err ? : -errno;
1469            }
1470        }
1471    }
1472    hwc_dev->last_ext_ovls = hwc_dev->ext_ovls;
1473    hwc_dev->last_int_ovls = hwc_dev->post2_layers;
1474    if (err)
1475        LOGE("Post2 error");
1476
1477err_out:
1478    pthread_mutex_unlock(&hwc_dev->lock);
1479
1480    if (invalidate && hwc_dev->procs && hwc_dev->procs->invalidate)
1481        hwc_dev->procs->invalidate(hwc_dev->procs);
1482
1483    return err;
1484}
1485
1486static void omap4_hwc_dump(struct hwc_composer_device *dev, char *buff, int buff_len)
1487{
1488    omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev;
1489    struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->dsscomp_data;
1490    struct dump_buf log = {
1491        .buf = buff,
1492        .buf_len = buff_len,
1493    };
1494    int i;
1495
1496    dump_printf(&log, "omap4_hwc %d:\n", dsscomp->num_ovls);
1497    dump_printf(&log, "  idle timeout: %dms\n", hwc_dev->idle);
1498
1499    for (i = 0; i < dsscomp->num_ovls; i++) {
1500        struct dss2_ovl_cfg *cfg = &dsscomp->ovls[i].cfg;
1501
1502        dump_printf(&log, "  layer %d:\n", i);
1503        dump_printf(&log, "     enabled: %s\n",
1504                          cfg->enabled ? "true" : "false");
1505        dump_printf(&log, "     buff: %p %dx%d stride: %d\n",
1506                          hwc_dev->buffers[i], cfg->width, cfg->height, cfg->stride);
1507        dump_printf(&log, "     src: (%d,%d) %dx%d\n",
1508                          cfg->crop.x, cfg->crop.y, cfg->crop.w, cfg->crop.h);
1509        dump_printf(&log, "     dst: (%d,%d) %dx%d\n",
1510                          cfg->win.x, cfg->win.y, cfg->win.w, cfg->win.h);
1511        dump_printf(&log, "     ix: %d\n", cfg->ix);
1512        dump_printf(&log, "     zorder: %d\n\n", cfg->zorder);
1513    }
1514}
1515
1516static void free_png_image(omap4_hwc_device_t *hwc_dev, struct omap4_hwc_img *img)
1517{
1518    memset(img, 0, sizeof(*img));
1519}
1520
1521static int load_png_image(omap4_hwc_device_t *hwc_dev, char *path, struct omap4_hwc_img *img)
1522{
1523    void *ptr = NULL;
1524    png_bytepp row_pointers = NULL;
1525
1526    FILE *fd = fopen(path, "rb");
1527    if (!fd) {
1528        LOGE("failed to open PNG file %s: (%d)", path, errno);
1529        return -EINVAL;
1530    }
1531
1532    const int SIZE_PNG_HEADER = 8;
1533    __u8 header[SIZE_PNG_HEADER];
1534    fread(header, 1, SIZE_PNG_HEADER, fd);
1535    if (png_sig_cmp(header, 0, SIZE_PNG_HEADER)) {
1536        LOGE("%s is not a PNG file", path);
1537        goto fail;
1538    }
1539
1540    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1541    if (!png_ptr)
1542         goto fail_alloc;
1543    png_infop info_ptr = png_create_info_struct(png_ptr);
1544    if (!info_ptr)
1545         goto fail_alloc;
1546
1547    if (setjmp(png_jmpbuf(png_ptr)))
1548        goto fail_alloc;
1549
1550    png_init_io(png_ptr, fd);
1551    png_set_sig_bytes(png_ptr, SIZE_PNG_HEADER);
1552    png_set_user_limits(png_ptr, limits.max_width, limits.max_height);
1553    png_read_info(png_ptr, info_ptr);
1554
1555    __u8 bit_depth = png_get_bit_depth(png_ptr, info_ptr);
1556    __u32 width = png_get_image_width(png_ptr, info_ptr);
1557    __u32 height = png_get_image_height(png_ptr, info_ptr);
1558    __u8 color_type = png_get_color_type(png_ptr, info_ptr);
1559
1560    switch (color_type) {
1561    case PNG_COLOR_TYPE_PALETTE:
1562        png_set_palette_to_rgb(png_ptr);
1563        png_set_filler(png_ptr, 128, PNG_FILLER_AFTER);
1564        break;
1565    case PNG_COLOR_TYPE_GRAY:
1566        if (bit_depth < 8) {
1567            png_set_expand_gray_1_2_4_to_8(png_ptr);
1568            if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
1569                png_set_tRNS_to_alpha(png_ptr);
1570        } else {
1571            png_set_filler(png_ptr, 128, PNG_FILLER_AFTER);
1572        }
1573        /* fall through */
1574    case PNG_COLOR_TYPE_GRAY_ALPHA:
1575        png_set_gray_to_rgb(png_ptr);
1576        break;
1577    case PNG_COLOR_TYPE_RGB:
1578        png_set_filler(png_ptr, 128, PNG_FILLER_AFTER);
1579        /* fall through */
1580    case PNG_COLOR_TYPE_RGB_ALPHA:
1581        png_set_bgr(png_ptr);
1582        break;
1583    default:
1584        LOGE("unsupported PNG color: %x", color_type);
1585        goto fail_alloc;
1586    }
1587
1588    if (bit_depth == 16)
1589        png_set_strip_16(png_ptr);
1590
1591    const int bpp = 4;
1592    img->size = ALIGN(width * height * bpp, 4096);
1593    if (img->size > hwc_dev->img_mem_size) {
1594        LOGE("image does not fit into framebuffer area (%d > %d)", img->size, hwc_dev->img_mem_size);
1595        goto fail_alloc;
1596    }
1597    img->ptr = hwc_dev->img_mem_ptr;
1598
1599    row_pointers = calloc(height, sizeof(*row_pointers));
1600    if (!row_pointers) {
1601        LOGE("failed to allocate row pointers");
1602        goto fail_alloc;
1603    }
1604    __u32 i;
1605    for (i = 0; i < height; i++)
1606        row_pointers[i] = img->ptr + i * width * bpp;
1607    png_set_rows(png_ptr, info_ptr, row_pointers);
1608    png_read_update_info(png_ptr, info_ptr);
1609    img->rowbytes = png_get_rowbytes(png_ptr, info_ptr);
1610
1611    png_read_image(png_ptr, row_pointers);
1612    png_read_end(png_ptr, NULL);
1613    free(row_pointers);
1614    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
1615    fclose(fd);
1616    img->width = width;
1617    img->height = height;
1618    return 0;
1619
1620fail_alloc:
1621    free_png_image(hwc_dev, img);
1622    free(row_pointers);
1623    if (!png_ptr || !info_ptr)
1624        LOGE("failed to allocate PNG structures");
1625    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
1626fail:
1627    fclose(fd);
1628    return -EINVAL;
1629}
1630
1631
1632static int omap4_hwc_device_close(hw_device_t* device)
1633{
1634    omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) device;;
1635
1636    if (hwc_dev) {
1637        if (hwc_dev->dsscomp_fd >= 0)
1638            close(hwc_dev->dsscomp_fd);
1639        if (hwc_dev->hdmi_fb_fd >= 0)
1640            close(hwc_dev->hdmi_fb_fd);
1641        if (hwc_dev->fb_fd >= 0)
1642            close(hwc_dev->fb_fd);
1643        /* pthread will get killed when parent process exits */
1644        pthread_mutex_destroy(&hwc_dev->lock);
1645        free(hwc_dev);
1646    }
1647
1648    return 0;
1649}
1650
1651static int omap4_hwc_open_fb_hal(IMG_framebuffer_device_public_t **fb_dev)
1652{
1653    const struct hw_module_t *psModule;
1654    IMG_gralloc_module_public_t *psGrallocModule;
1655    int err;
1656
1657    err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &psModule);
1658    psGrallocModule = (IMG_gralloc_module_public_t *) psModule;
1659
1660    if(err)
1661        goto err_out;
1662
1663    if (strcmp(psGrallocModule->base.common.author, "Imagination Technologies")) {
1664        err = -EINVAL;
1665        goto err_out;
1666    }
1667
1668    *fb_dev = psGrallocModule->psFrameBufferDevice;
1669
1670    return 0;
1671
1672err_out:
1673    LOGE("Composer HAL failed to load compatible Graphics HAL");
1674    return err;
1675}
1676
1677static void handle_hotplug(omap4_hwc_device_t *hwc_dev)
1678{
1679    omap4_hwc_ext_t *ext = &hwc_dev->ext;
1680    __u8 state = ext->hdmi_state;
1681
1682    pthread_mutex_lock(&hwc_dev->lock);
1683    ext->dock.enabled = ext->mirror.enabled = 0;
1684    if (state) {
1685        /* check whether we can clone and/or dock */
1686        char value[PROPERTY_VALUE_MAX];
1687        property_get("persist.hwc.docking.enabled", value, "1");
1688        ext->dock.enabled = atoi(value) > 0;
1689        property_get("persist.hwc.mirroring.enabled", value, "1");
1690        ext->mirror.enabled = atoi(value) > 0;
1691        property_get("persist.hwc.avoid_mode_change", value, "1");
1692        ext->avoid_mode_change = atoi(value) > 0;
1693
1694        /* get cloning transformation */
1695        property_get("persist.hwc.docking.transform", value, "0");
1696        ext->dock.rotation = atoi(value) & EXT_ROTATION;
1697        ext->dock.hflip = (atoi(value) & EXT_HFLIP) > 0;
1698        ext->dock.docking = 1;
1699        property_get("persist.hwc.mirroring.transform", value, hwc_dev->fb_dev->base.height > hwc_dev->fb_dev->base.width ? "3" : "0");
1700        ext->mirror.rotation = atoi(value) & EXT_ROTATION;
1701        ext->mirror.hflip = (atoi(value) & EXT_HFLIP) > 0;
1702        ext->mirror.docking = 0;
1703
1704        if (ext->force_dock) {
1705            /* restrict to docking with no transform */
1706            ext->mirror.enabled = 0;
1707            ext->dock.rotation = 0;
1708            ext->dock.hflip = 0;
1709
1710            if (!dock_image.rowbytes) {
1711                property_get("persist.hwc.dock_image", value, "/vendor/res/images/dock/dock.png");
1712                load_png_image(hwc_dev, value, &dock_image);
1713            }
1714        }
1715
1716        /* select best mode for mirroring */
1717        if (ext->mirror.enabled) {
1718            ext->current = ext->mirror;
1719            ext->mirror_mode = 0;
1720            if (setup_mirroring(hwc_dev) == 0) {
1721                ext->mirror_mode = ext->last_mode;
1722                ioctl(hwc_dev->hdmi_fb_fd, FBIOBLANK, FB_BLANK_UNBLANK);
1723            } else
1724                ext->mirror.enabled = 0;
1725        }
1726    } else {
1727        ext->last_mode = 0;
1728    }
1729    LOGI("external display changed (state=%d, mirror={%s tform=%ddeg%s}, dock={%s tform=%ddeg%s%s}, tv=%d", state,
1730         ext->mirror.enabled ? "enabled" : "disabled",
1731         ext->mirror.rotation * 90,
1732         ext->mirror.hflip ? "+hflip" : "",
1733         ext->dock.enabled ? "enabled" : "disabled",
1734         ext->dock.rotation * 90,
1735         ext->dock.hflip ? "+hflip" : "",
1736         ext->force_dock ? " forced" : "",
1737         ext->on_tv);
1738
1739    pthread_mutex_unlock(&hwc_dev->lock);
1740
1741    if (hwc_dev->procs && hwc_dev->procs->invalidate)
1742            hwc_dev->procs->invalidate(hwc_dev->procs);
1743}
1744
1745static void handle_uevents(omap4_hwc_device_t *hwc_dev, const char *s)
1746{
1747    int dock = !strcmp(s, "change@/devices/virtual/switch/dock");
1748    if (!dock &&
1749        strcmp(s, "change@/devices/virtual/switch/hdmi"))
1750        return;
1751
1752    s += strlen(s) + 1;
1753
1754    while(*s) {
1755        if (!strncmp(s, "SWITCH_STATE=", strlen("SWITCH_STATE="))) {
1756            int state = atoi(s + strlen("SWITCH_STATE="));
1757            if (dock)
1758                hwc_dev->ext.force_dock = state == 1;
1759            else
1760                hwc_dev->ext.hdmi_state = state == 1;
1761            handle_hotplug(hwc_dev);
1762        }
1763
1764        s += strlen(s) + 1;
1765    }
1766}
1767
1768static void *omap4_hwc_hdmi_thread(void *data)
1769{
1770    omap4_hwc_device_t *hwc_dev = data;
1771    static char uevent_desc[4096];
1772    struct pollfd fds[2];
1773    int invalidate = 0;
1774    int timeout;
1775    int err;
1776
1777    uevent_init();
1778
1779    fds[0].fd = uevent_get_fd();
1780    fds[0].events = POLLIN;
1781    fds[1].fd = hwc_dev->pipe_fds[0];
1782    fds[1].events = POLLIN;
1783
1784    timeout = hwc_dev->idle ? hwc_dev->idle : -1;
1785
1786    memset(uevent_desc, 0, sizeof(uevent_desc));
1787
1788    do {
1789        err = poll(fds, hwc_dev->idle ? 2 : 1, timeout);
1790
1791        if (err == 0) {
1792            if (hwc_dev->idle) {
1793                if (hwc_dev->procs && hwc_dev->procs->invalidate) {
1794                    pthread_mutex_lock(&hwc_dev->lock);
1795                    invalidate = !hwc_dev->force_sgx && hwc_dev->ovls_blending;
1796                    if (invalidate) {
1797                        hwc_dev->force_sgx = 2;
1798                    }
1799                    pthread_mutex_unlock(&hwc_dev->lock);
1800
1801                    if (invalidate) {
1802                        hwc_dev->procs->invalidate(hwc_dev->procs);
1803                        timeout = -1;
1804                    }
1805                }
1806
1807                continue;
1808            }
1809        }
1810
1811        if (err == -1) {
1812            if (errno != EINTR)
1813                LOGE("event error: %m");
1814            continue;
1815        }
1816
1817        if (hwc_dev->idle && fds[1].revents & POLLIN) {
1818            char c;
1819            read(hwc_dev->pipe_fds[0], &c, 1);
1820            if (!hwc_dev->force_sgx)
1821                timeout = hwc_dev->idle ? hwc_dev->idle : -1;
1822        }
1823
1824        if (fds[0].revents & POLLIN) {
1825            /* keep last 2 zeroes to ensure double 0 termination */
1826            uevent_next_event(uevent_desc, sizeof(uevent_desc) - 2);
1827            handle_uevents(hwc_dev, uevent_desc);
1828        }
1829    } while (1);
1830
1831    return NULL;
1832}
1833
1834static void omap4_hwc_registerProcs(struct hwc_composer_device* dev,
1835                                    hwc_procs_t const* procs)
1836{
1837    omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) dev;
1838
1839    hwc_dev->procs = (typeof(hwc_dev->procs)) procs;
1840}
1841
1842static int omap4_hwc_device_open(const hw_module_t* module, const char* name,
1843                hw_device_t** device)
1844{
1845    omap4_hwc_module_t *hwc_mod = (omap4_hwc_module_t *)module;
1846    omap4_hwc_device_t *hwc_dev;
1847    int err = 0;
1848
1849    if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
1850        return -EINVAL;
1851    }
1852
1853    if (!hwc_mod->fb_dev) {
1854        err = omap4_hwc_open_fb_hal(&hwc_mod->fb_dev);
1855        if (err)
1856            return err;
1857
1858        if (!hwc_mod->fb_dev) {
1859            LOGE("Framebuffer HAL not opened before HWC");
1860            return -EFAULT;
1861        }
1862        hwc_mod->fb_dev->bBypassPost = 1;
1863    }
1864
1865    hwc_dev = (omap4_hwc_device_t *)malloc(sizeof(*hwc_dev));
1866    if (hwc_dev == NULL)
1867        return -ENOMEM;
1868
1869    memset(hwc_dev, 0, sizeof(*hwc_dev));
1870
1871    hwc_dev->base.common.tag = HARDWARE_DEVICE_TAG;
1872    hwc_dev->base.common.version = HWC_API_VERSION;
1873    hwc_dev->base.common.module = (hw_module_t *)module;
1874    hwc_dev->base.common.close = omap4_hwc_device_close;
1875    hwc_dev->base.prepare = omap4_hwc_prepare;
1876    hwc_dev->base.set = omap4_hwc_set;
1877    hwc_dev->base.dump = omap4_hwc_dump;
1878    hwc_dev->base.registerProcs = omap4_hwc_registerProcs;
1879    hwc_dev->fb_dev = hwc_mod->fb_dev;
1880    *device = &hwc_dev->base.common;
1881
1882    hwc_dev->dsscomp_fd = open("/dev/dsscomp", O_RDWR);
1883    if (hwc_dev->dsscomp_fd < 0) {
1884        LOGE("failed to open dsscomp (%d)", errno);
1885        err = -errno;
1886        goto done;
1887    }
1888
1889    hwc_dev->hdmi_fb_fd = open("/dev/graphics/fb1", O_RDWR);
1890    if (hwc_dev->hdmi_fb_fd < 0) {
1891        LOGE("failed to open hdmi fb (%d)", errno);
1892        err = -errno;
1893        goto done;
1894    }
1895
1896    hwc_dev->fb_fd = open("/dev/graphics/fb0", O_RDWR);
1897    if (hwc_dev->fb_fd < 0) {
1898        LOGE("failed to open fb (%d)", errno);
1899        err = -errno;
1900        goto done;
1901    }
1902
1903    struct fb_fix_screeninfo fix;
1904    if (ioctl(hwc_dev->fb_fd, FBIOGET_FSCREENINFO, &fix)) {
1905        LOGE("failed to get fb info (%d)", errno);
1906        err = -errno;
1907        goto done;
1908    }
1909
1910    hwc_dev->img_mem_size = fix.smem_len;
1911    hwc_dev->img_mem_ptr = mmap(NULL, fix.smem_len, PROT_WRITE, MAP_SHARED, hwc_dev->fb_fd, 0);
1912    if (hwc_dev->img_mem_ptr == MAP_FAILED) {
1913        LOGE("failed to map fb memory");
1914        err = -errno;
1915        goto done;
1916    }
1917
1918    hwc_dev->buffers = malloc(sizeof(buffer_handle_t) * MAX_HW_OVERLAYS);
1919    if (!hwc_dev->buffers) {
1920        err = -ENOMEM;
1921        goto done;
1922    }
1923
1924    int ret = ioctl(hwc_dev->dsscomp_fd, DSSCIOC_QUERY_DISPLAY, &hwc_dev->fb_dis);
1925    if (ret) {
1926        LOGE("failed to get display info (%d): %m", errno);
1927        err = -errno;
1928        goto done;
1929    }
1930    hwc_dev->ext.lcd_xpy = (float) hwc_dev->fb_dis.width_in_mm / hwc_dev->fb_dis.timings.x_res /
1931                            hwc_dev->fb_dis.height_in_mm       * hwc_dev->fb_dis.timings.y_res;
1932
1933    if (pipe(hwc_dev->pipe_fds) == -1) {
1934            LOGE("failed to event pipe (%d): %m", errno);
1935            err = -errno;
1936            goto done;
1937    }
1938
1939    if (pthread_mutex_init(&hwc_dev->lock, NULL)) {
1940        LOGE("failed to create mutex (%d): %m", errno);
1941        err = -errno;
1942        goto done;
1943    }
1944    if (pthread_create(&hwc_dev->hdmi_thread, NULL, omap4_hwc_hdmi_thread, hwc_dev))
1945    {
1946        LOGE("failed to create HDMI listening thread (%d): %m", errno);
1947        err = -errno;
1948        goto done;
1949    }
1950
1951    /* get debug properties */
1952
1953    /* see if hwc is enabled at all */
1954    char value[PROPERTY_VALUE_MAX];
1955    property_get("debug.hwc.rgb_order", value, "1");
1956    hwc_dev->flags_rgb_order = atoi(value);
1957    property_get("debug.hwc.nv12_only", value, "0");
1958    hwc_dev->flags_nv12_only = atoi(value);
1959    property_get("debug.hwc.idle", value, "250");
1960    hwc_dev->idle = atoi(value);
1961
1962    /* get the board specific clone properties */
1963    /* 0:0:1280:720 */
1964    if (property_get("persist.hwc.mirroring.region", value, "") <= 0 ||
1965        sscanf(value, "%d:%d:%d:%d",
1966               &hwc_dev->ext.mirror_region.left, &hwc_dev->ext.mirror_region.top,
1967               &hwc_dev->ext.mirror_region.right, &hwc_dev->ext.mirror_region.bottom) != 4 ||
1968        hwc_dev->ext.mirror_region.left >= hwc_dev->ext.mirror_region.right ||
1969        hwc_dev->ext.mirror_region.top >= hwc_dev->ext.mirror_region.bottom) {
1970        struct hwc_rect fb_region = { .right = hwc_dev->fb_dev->base.width, .bottom = hwc_dev->fb_dev->base.height };
1971        hwc_dev->ext.mirror_region = fb_region;
1972    }
1973    LOGI("clone region is set to (%d,%d) to (%d,%d)",
1974         hwc_dev->ext.mirror_region.left, hwc_dev->ext.mirror_region.top,
1975         hwc_dev->ext.mirror_region.right, hwc_dev->ext.mirror_region.bottom);
1976
1977    /* read switch state */
1978    int sw_fd = open("/sys/class/switch/hdmi/state", O_RDONLY);
1979    if (sw_fd >= 0) {
1980        char value;
1981        if (read(sw_fd, &value, 1) == 1)
1982            hwc_dev->ext.hdmi_state = value == '1';
1983        close(sw_fd);
1984    }
1985    sw_fd = open("/sys/class/switch/dock/state", O_RDONLY);
1986    if (sw_fd >= 0) {
1987        char value;
1988        if (read(sw_fd, &value, 1) == 1)
1989            hwc_dev->ext.force_dock = value == '1';
1990        close(sw_fd);
1991    }
1992    handle_hotplug(hwc_dev);
1993
1994    LOGI("omap4_hwc_device_open(rgb_order=%d nv12_only=%d)",
1995        hwc_dev->flags_rgb_order, hwc_dev->flags_nv12_only);
1996
1997done:
1998    if (err && hwc_dev) {
1999        if (hwc_dev->dsscomp_fd >= 0)
2000            close(hwc_dev->dsscomp_fd);
2001        if (hwc_dev->hdmi_fb_fd >= 0)
2002            close(hwc_dev->hdmi_fb_fd);
2003        if (hwc_dev->fb_fd >= 0)
2004            close(hwc_dev->fb_fd);
2005        pthread_mutex_destroy(&hwc_dev->lock);
2006        free(hwc_dev->buffers);
2007        free(hwc_dev);
2008    }
2009
2010    return err;
2011}
2012
2013static struct hw_module_methods_t omap4_hwc_module_methods = {
2014    .open = omap4_hwc_device_open,
2015};
2016
2017omap4_hwc_module_t HAL_MODULE_INFO_SYM = {
2018    .base = {
2019        .common = {
2020            .tag =                  HARDWARE_MODULE_TAG,
2021            .version_major =        1,
2022            .version_minor =        0,
2023            .id =                   HWC_HARDWARE_MODULE_ID,
2024            .name =                 "OMAP 44xx Hardware Composer HAL",
2025            .author =               "Texas Instruments",
2026            .methods =              &omap4_hwc_module_methods,
2027        },
2028    },
2029};
2030