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