hwc.c revision 7f2cbf97908a26e0b463d4fa20040b129216f86e
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 <sys/ioctl.h>
23#include <linux/fb.h>
24
25#include <cutils/properties.h>
26#include <cutils/log.h>
27#include <cutils/native_handle.h>
28#include <hardware/hardware.h>
29#include <hardware/hwcomposer.h>
30#include <EGL/egl.h>
31#include <utils/Timers.h>
32#include <hardware_legacy/uevent.h>
33
34#define ASPECT_RATIO_TOLERANCE 0.02f
35
36#ifndef FBIO_WAITFORVSYNC
37#define FBIO_WAITFORVSYNC	_IOW('F', 0x20, __u32)
38#endif
39
40#define min(a, b) ( { typeof(a) __a = (a), __b = (b); __a < __b ? __a : __b; } )
41#define max(a, b) ( { typeof(a) __a = (a), __b = (b); __a > __b ? __a : __b; } )
42
43#include <video/dsscomp.h>
44
45#include "hal_public.h"
46
47#define MAX_HW_OVERLAYS 4
48#define NUM_NONSCALING_OVERLAYS 1
49#define HAL_PIXEL_FORMAT_BGRX_8888		0x1FF
50#define HAL_PIXEL_FORMAT_TI_NV12 0x100
51#define HAL_PIXEL_FORMAT_TI_NV12_PADDED 0x101
52#define MAX_TILER_SLOT (16 << 20)
53
54#define MIN(a,b)		  ((a)<(b)?(a):(b))
55#define MAX(a,b)		  ((a)>(b)?(a):(b))
56#define CLAMP(x,low,high) (((x)>(high))?(high):(((x)<(low))?(low):(x)))
57
58enum {
59    EXT_ROTATION    = 3,        /* rotation while mirroring */
60    EXT_HFLIP       = (1 << 2), /* flip l-r on output (after rotation) */
61    EXT_TRANSFORM   = EXT_ROTATION | EXT_HFLIP,
62    EXT_ON          = (1 << 3), /* copy output to other display */
63    EXT_DOCK        = (1 << 4), /* docking only */
64    EXT_TV          = (1 << 5), /* using TV for mirroring */
65};
66
67struct omap4_hwc_module {
68    hwc_module_t base;
69
70    IMG_framebuffer_device_public_t *fb_dev;
71};
72typedef struct omap4_hwc_module omap4_hwc_module_t;
73
74struct omap4_hwc_device {
75    hwc_composer_device_t base;
76    hwc_procs_t *procs;
77    pthread_t hdmi_thread;
78    pthread_mutex_t lock;
79    int dsscomp_fd;
80    int fb_fd;
81    int hdmi_fb_fd;
82
83    __u16 ext_width;
84    __u16 ext_height;
85    __u32 ext_xres;
86    __u32 ext_yres;
87    float m[2][3];
88    IMG_framebuffer_device_public_t *fb_dev;
89    struct dsscomp_setup_dispc_data dsscomp_data;
90    struct dsscomp_display_info fb_dis;
91
92    buffer_handle_t *buffers;
93    int use_sgx;
94    int swap_rb;
95    int use_tv;
96    int mirror;
97    unsigned int post2_layers;
98    int last_ext_ovls;
99    int last_int_ovls;
100    int ext_ovls;
101
102    int flags_rgb_order;
103    int flags_nv12_only;
104    int ext;
105};
106typedef struct omap4_hwc_device omap4_hwc_device_t;
107
108static int debug = 0;
109
110static void dump_layer(hwc_layer_t const* l)
111{
112    LOGD("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}",
113            l->compositionType, l->flags, l->handle, l->transform, l->blending,
114            l->sourceCrop.left,
115            l->sourceCrop.top,
116            l->sourceCrop.right,
117            l->sourceCrop.bottom,
118            l->displayFrame.left,
119            l->displayFrame.top,
120            l->displayFrame.right,
121            l->displayFrame.bottom);
122}
123
124static void dump_dsscomp(struct dsscomp_setup_dispc_data *d)
125{
126    unsigned i;
127
128    LOGD("[%08x] set: %c%c%c %d ovls\n",
129         d->sync_id,
130         (d->mode & DSSCOMP_SETUP_MODE_APPLY) ? 'A' : '-',
131         (d->mode & DSSCOMP_SETUP_MODE_DISPLAY) ? 'D' : '-',
132         (d->mode & DSSCOMP_SETUP_MODE_CAPTURE) ? 'C' : '-',
133         d->num_ovls);
134
135    for (i = 0; i < d->num_mgrs; i++) {
136        struct dss2_mgr_info *mi = d->mgrs + i;
137        LOGD(" (dis%d alpha=%d col=%08x ilace=%d)\n",
138            mi->ix,
139            mi->alpha_blending, mi->default_color,
140            mi->interlaced);
141    }
142
143    for (i = 0; i < d->num_ovls; i++) {
144            struct dss2_ovl_info *oi = d->ovls + i;
145            struct dss2_ovl_cfg *c = &oi->cfg;
146            if (c->zonly)
147                    LOGE("ovl%d(%s z%d)\n",
148                         c->ix, c->enabled ? "ON" : "off", c->zorder);
149            else
150                    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",
151                         c->ix, c->enabled ? "ON" : "off", c->zorder, c->color_mode,
152                         c->pre_mult_alpha ? " premult" : "",
153                         (c->global_alpha * 100 + 128) / 255,
154                         c->width, c->height, c->crop.x, c->crop.y,
155                         c->crop.w, c->crop.h,
156                         c->rotation, c->mirror ? "+mir" : "",
157                         c->win.x, c->win.y, c->win.w, c->win.h,
158                         (void *) oi->ba, (void *) oi->uv, c->stride);
159    }
160}
161
162static int omap4_hwc_is_valid_format(int format)
163{
164    switch(format) {
165    case HAL_PIXEL_FORMAT_RGB_565:
166    case HAL_PIXEL_FORMAT_RGBX_8888:
167    case HAL_PIXEL_FORMAT_RGBA_8888:
168    case HAL_PIXEL_FORMAT_BGRA_8888:
169    case HAL_PIXEL_FORMAT_BGRX_8888:
170    case HAL_PIXEL_FORMAT_TI_NV12:
171    case HAL_PIXEL_FORMAT_TI_NV12_PADDED:
172        return 1;
173
174    default:
175        LOGI("invalid format %d", format);
176        return 0;
177    }
178}
179
180static int scaled(hwc_layer_t *layer)
181{
182    int w = layer->sourceCrop.right - layer->sourceCrop.left;
183    int h = layer->sourceCrop.bottom - layer->sourceCrop.top;
184
185    if (layer->transform & HWC_TRANSFORM_ROT_90) {
186        int t = w;
187        w = h;
188        h = t;
189    }
190
191    return (layer->displayFrame.right - layer->displayFrame.left != w ||
192            layer->displayFrame.bottom - layer->displayFrame.top != h);
193}
194
195static int sync_id = 0;
196
197#define is_BLENDED(blending) ((blending) != HWC_BLENDING_NONE)
198
199#define is_RGB(format) ((format) == HAL_PIXEL_FORMAT_BGRA_8888 || (format) == HAL_PIXEL_FORMAT_RGB_565 || (format) == HAL_PIXEL_FORMAT_BGRX_8888)
200#define is_BGR(format) ((format) == HAL_PIXEL_FORMAT_RGBX_8888 || (format) == HAL_PIXEL_FORMAT_RGBA_8888)
201#define is_NV12(format) ((format) == HAL_PIXEL_FORMAT_TI_NV12 || (format) == HAL_PIXEL_FORMAT_TI_NV12_PADDED)
202
203static unsigned int mem1d(IMG_native_handle_t *handle)
204{
205    if (handle == NULL)
206            return 0;
207
208    int bpp = is_NV12(handle->iFormat) ? 0 : (handle->iFormat == HAL_PIXEL_FORMAT_RGB_565 ? 2 : 4);
209    int stride = ALIGN(handle->iWidth, HW_ALIGN) * bpp;
210    return stride * handle->iHeight;
211}
212
213static void
214omap4_hwc_setup_layer_base(struct dss2_ovl_cfg *oc, int index, int format, int width, int height)
215{
216    unsigned int bits_per_pixel;
217
218    /* YUV2RGB conversion */
219    const struct omap_dss_cconv_coefs ctbl_bt601_5 = {
220        298,  409,    0,  298, -208, -100,  298,    0,  517, 0,
221    };
222
223    /* convert color format */
224    switch (format) {
225    case HAL_PIXEL_FORMAT_RGBX_8888:
226        /* Should be XBGR32, but this isn't supported */
227        oc->color_mode = OMAP_DSS_COLOR_RGB24U;
228        bits_per_pixel = 32;
229        break;
230
231    case HAL_PIXEL_FORMAT_RGBA_8888:
232        /* Should be ABGR32, but this isn't supported */
233        oc->color_mode = OMAP_DSS_COLOR_ARGB32;
234        bits_per_pixel = 32;
235        break;
236
237    case HAL_PIXEL_FORMAT_BGRA_8888:
238        oc->color_mode = OMAP_DSS_COLOR_ARGB32;
239        bits_per_pixel = 32;
240        break;
241
242    case HAL_PIXEL_FORMAT_BGRX_8888:
243        oc->color_mode = OMAP_DSS_COLOR_RGB24U;
244        bits_per_pixel = 32;
245        break;
246
247    case HAL_PIXEL_FORMAT_RGB_565:
248        oc->color_mode = OMAP_DSS_COLOR_RGB16;
249        bits_per_pixel = 16;
250        break;
251
252    case HAL_PIXEL_FORMAT_TI_NV12:
253    case HAL_PIXEL_FORMAT_TI_NV12_PADDED:
254        oc->color_mode = OMAP_DSS_COLOR_NV12;
255        bits_per_pixel = 8;
256        oc->cconv = ctbl_bt601_5;
257        break;
258
259    default:
260        /* Should have been filtered out */
261        LOGV("Unsupported pixel format");
262        return;
263    }
264
265    oc->width = width;
266    oc->height = height;
267    oc->stride = ALIGN(width, HW_ALIGN) * bits_per_pixel / 8;
268
269    oc->enabled = 1;
270    oc->global_alpha = 255;
271    oc->zorder = index;
272    oc->ix = 0;
273
274    /* defaults for SGX framebuffer renders */
275    oc->crop.w = oc->win.w = width;
276    oc->crop.h = oc->win.h = height;
277
278    /* for now interlacing and vc1 info is not supplied */
279    oc->ilace = OMAP_DSS_ILACE_NONE;
280    oc->vc1.enable = 0;
281}
282
283static void
284omap4_hwc_setup_layer(omap4_hwc_device_t *hwc_dev, struct dss2_ovl_info *ovl,
285                      hwc_layer_t *layer, int index,
286                      int format, int width, int height)
287{
288    struct dss2_ovl_cfg *oc = &ovl->cfg;
289
290    //dump_layer(layer);
291
292    if (format == HAL_PIXEL_FORMAT_BGRA_8888 && !is_BLENDED(layer->blending)) {
293        format = HAL_PIXEL_FORMAT_BGRX_8888;
294    }
295
296    omap4_hwc_setup_layer_base(oc, index, format, width, height);
297
298    /* convert transformation - assuming 0-set config */
299    if (layer->transform & HWC_TRANSFORM_FLIP_H)
300        oc->mirror = 1;
301    if (layer->transform & HWC_TRANSFORM_FLIP_V) {
302        oc->rotation = 2;
303        oc->mirror = !oc->mirror;
304    }
305    if (layer->transform & HWC_TRANSFORM_ROT_90) {
306        oc->rotation += oc->mirror ? -1 : 1;
307        oc->rotation &= 3;
308    }
309
310    oc->pre_mult_alpha = layer->blending == HWC_BLENDING_PREMULT;
311
312    /* display position */
313    oc->win.x = layer->displayFrame.left;
314    oc->win.y = layer->displayFrame.top;
315    oc->win.w = layer->displayFrame.right - layer->displayFrame.left;
316    oc->win.h = layer->displayFrame.bottom - layer->displayFrame.top;
317
318    /* crop */
319    oc->crop.x = layer->sourceCrop.left;
320    oc->crop.y = layer->sourceCrop.top;
321    oc->crop.w = layer->sourceCrop.right - layer->sourceCrop.left;
322    oc->crop.h = layer->sourceCrop.bottom - layer->sourceCrop.top;
323}
324
325const float m_unit[2][3] = { { 1., 0., 0. }, { 0., 1., 0. } };
326
327static inline void m_translate(float m[2][3], int dx, int dy)
328{
329    m[0][2] += dx;
330    m[1][2] += dy;
331}
332
333static inline void m_scale1(float m[3], int from, int to)
334{
335    m[0] = m[0] * to / from;
336    m[1] = m[1] * to / from;
337    m[2] = m[2] * to / from;
338}
339
340static inline void m_scale(float m[2][3], int x_from, int x_to, int y_from, int y_to)
341{
342    m_scale1(m[0], x_from, x_to);
343    m_scale1(m[1], y_from, y_to);
344}
345
346static void m_rotate(float m[2][3], int quarter_turns)
347{
348    if (quarter_turns & 2)
349        m_scale(m, 1, -1, 1, -1);
350    if (quarter_turns & 1) {
351        int q;
352        q = m[0][0]; m[0][0] = -m[1][0]; m[1][0] = q;
353        q = m[0][1]; m[0][1] = -m[1][1]; m[1][1] = q;
354        q = m[0][2]; m[0][2] = -m[1][2]; m[1][2] = q;
355    }
356}
357
358static inline int m_round(float x)
359{
360    /* int truncates towards 0 */
361    return (int) (x < 0 ? x - 0.5 : x + 0.5);
362}
363
364/*
365 * assuming xratio:yratio original pixel ratio, calculate the adjusted width
366 * and height for a screen of xres/yres and physical size of width/height.
367 * The adjusted size is the largest that fits into the screen.
368 */
369static void get_max_dimensions(__u32 orig_xres, __u32 orig_yres,
370                               __u32 orig_xratio, __u32 orig_yratio,
371                               __u32 scr_xres, __u32 scr_yres,
372                               __u32 scr_width, __u32 scr_height,
373                               __u32 *adj_xres, __u32 *adj_yres)
374{
375    /* assume full screen (largest size)*/
376    *adj_xres = scr_xres;
377    *adj_yres = scr_yres;
378
379    /* assume 1:1 pixel ratios if none supplied */
380    if (!scr_width || !scr_height) {
381        scr_width = scr_xres;
382        scr_height = scr_yres;
383    }
384    if (!orig_xratio || !orig_yratio) {
385        orig_xratio = 1;
386        orig_yratio = 1;
387    }
388
389    /* trim to keep aspect ratio */
390    float x_factor = orig_xres * orig_xratio * (float) scr_height;
391    float y_factor = orig_yres * orig_yratio * (float) scr_width;
392
393    /* allow for tolerance so we avoid scaling if framebuffer is standard size */
394    if (x_factor < y_factor * (1.f - ASPECT_RATIO_TOLERANCE))
395        *adj_xres = (__u32) (x_factor * *adj_xres / y_factor + 0.5);
396    else if (x_factor * (1.f - ASPECT_RATIO_TOLERANCE) > y_factor)
397        *adj_yres = (__u32) (y_factor * *adj_yres / x_factor + 0.5);
398}
399
400static void set_ext_matrix(omap4_hwc_device_t *hwc_dev, int orig_w, int orig_h)
401{
402    /* assume 1:1 lcd pixel ratio */
403    int source_x = 1;
404    int source_y = 1;
405
406    /* reorientation matrix is:
407       m = (center-from-target-center) * (scale-to-target) * (mirror) * (rotate) * (center-to-original-center) */
408
409    memcpy(hwc_dev->m, m_unit, sizeof(m_unit));
410    m_translate(hwc_dev->m, -orig_w >> 1, -orig_h >> 1);
411    m_rotate(hwc_dev->m, hwc_dev->ext & 3);
412    if (hwc_dev->ext & EXT_HFLIP)
413        m_scale(hwc_dev->m, 1, -1, 1, 1);
414
415    if (hwc_dev->ext & EXT_ROTATION & 1) {
416        int q = orig_w;
417        orig_w = orig_h;
418        orig_h = q;
419        q = source_x;
420        source_x = source_y;
421        source_y = q;
422    }
423
424    /* get target size */
425    __u32 adj_xres, adj_yres;
426    get_max_dimensions(orig_w, orig_h, source_x, source_y,
427                       hwc_dev->ext_xres, hwc_dev->ext_yres, hwc_dev->ext_width, hwc_dev->ext_height,
428                       &adj_xres, &adj_yres);
429
430    m_scale(hwc_dev->m, orig_w, adj_xres, orig_h, adj_yres);
431    m_translate(hwc_dev->m, hwc_dev->ext_xres >> 1, hwc_dev->ext_yres >> 1);
432}
433
434static void
435omap4_hwc_create_ext_matrix(omap4_hwc_device_t *hwc_dev)
436{
437    /* use VGA external resolution as default */
438    if (!hwc_dev->ext_xres ||
439        !hwc_dev->ext_yres) {
440        hwc_dev->ext_xres = 640;
441        hwc_dev->ext_yres = 480;
442    }
443
444    /* if docking, we cannot create the matrix ahead of time as it depends on input size */
445    if (hwc_dev->ext && !(hwc_dev->ext & EXT_DOCK))
446        set_ext_matrix(hwc_dev, hwc_dev->fb_dev->base.width, hwc_dev->fb_dev->base.height);
447}
448
449static void
450omap4_hwc_adjust_ext_layer(omap4_hwc_device_t *hwc_dev, struct dss2_ovl_info *ovl)
451{
452    struct dss2_ovl_cfg *oc = &ovl->cfg;
453    float x, y, w, h;
454
455    /* display position */
456    x = hwc_dev->m[0][0] * oc->win.x + hwc_dev->m[0][1] * oc->win.y + hwc_dev->m[0][2];
457    y = hwc_dev->m[1][0] * oc->win.x + hwc_dev->m[1][1] * oc->win.y + hwc_dev->m[1][2];
458    w = hwc_dev->m[0][0] * oc->win.w + hwc_dev->m[0][1] * oc->win.h;
459    h = hwc_dev->m[1][0] * oc->win.w + hwc_dev->m[1][1] * oc->win.h;
460    oc->win.x = m_round(w > 0 ? x : x + w);
461    oc->win.y = m_round(h > 0 ? y : y + h);
462    oc->win.w = m_round(w > 0 ? w : -w);
463    oc->win.h = m_round(h > 0 ? h : -h);
464
465    /* combining transformations: F^a*R^b*F^i*R^j = F^(a+b)*R^(j+b*(-1)^i), because F*R = R^(-1)*F */
466    oc->rotation += (oc->mirror ? -1 : 1) * (hwc_dev->ext & EXT_ROTATION);
467    oc->rotation &= 3;
468    if (hwc_dev->ext & EXT_HFLIP)
469        oc->mirror = !oc->mirror;
470}
471
472static struct dsscomp_dispc_limitations {
473    __u8 max_xdecim_2d;
474    __u8 max_ydecim_2d;
475    __u8 max_xdecim_1d;
476    __u8 max_ydecim_1d;
477    __u32 fclk;
478    __u8 max_downscale;
479    __u8 min_width;
480    __u16 integer_scale_ratio_limit;
481} limits = {
482    .max_xdecim_1d = 16,
483    .max_xdecim_2d = 16,
484    .max_ydecim_1d = 16,
485    .max_ydecim_2d = 2,
486    .fclk = 170666666,
487    .max_downscale = 4,
488    .min_width = 2,
489    .integer_scale_ratio_limit = 2048,
490};
491
492static int omap4_hwc_can_scale(int src_w, int src_h, int dst_w, int dst_h, int is_nv12,
493                               struct dsscomp_display_info *dis, struct dsscomp_dispc_limitations *limits)
494{
495    __u32 fclk = limits->fclk / 1000;
496    __u32 pclk = dis->timings.pixel_clock;
497
498    /* ERRATAs */
499    /* cannot render 1-width layers on DSI video mode panels - we just disallow all 1-width LCD layers */
500    if (dis->channel != OMAP_DSS_CHANNEL_DIGIT && dst_w < limits->min_width)
501        return 0;
502
503    /* NOTE: no support for checking YUV422 layers that are tricky to scale */
504
505    /* max downscale */
506    if (dst_h < src_h / limits->max_downscale / (is_nv12 ? limits->max_ydecim_2d : limits->max_ydecim_1d))
507        return 0;
508
509    /* :HACK: limit horizontal downscale well below theoretical limit as we saw display artifacts */
510    if (dst_w < src_w / 4)
511        return 0;
512
513    /* max horizontal downscale is 4, or the fclk/pixclk */
514    if (fclk > pclk * limits->max_downscale)
515        fclk = pclk * limits->max_downscale;
516    /* for small parts, we need to use integer fclk/pixclk */
517    if (src_w < limits->integer_scale_ratio_limit)
518        fclk = fclk / pclk * pclk;
519    if (dst_w < src_w * pclk / fclk / (is_nv12 ? limits->max_xdecim_2d : limits->max_xdecim_1d))
520        return 0;
521
522    return 1;
523}
524
525static int omap4_hwc_can_scale_layer(omap4_hwc_device_t *hwc_dev, hwc_layer_t *layer, IMG_native_handle_t *handle)
526{
527    int src_w = layer->sourceCrop.right - layer->sourceCrop.left;
528    int src_h = layer->sourceCrop.bottom - layer->sourceCrop.top;
529    int dst_w = layer->displayFrame.right - layer->displayFrame.left;
530    int dst_h = layer->displayFrame.bottom - layer->displayFrame.top;
531
532    /* account for 90-degree rotation */
533    if (layer->transform & HWC_TRANSFORM_ROT_90) {
534        int tmp = src_w;
535        src_w = src_h;
536        src_h = tmp;
537    }
538
539    return omap4_hwc_can_scale(src_w, src_h, dst_w, dst_h, is_NV12(handle->iFormat), &hwc_dev->fb_dis, &limits);
540}
541
542static int omap4_hwc_is_valid_layer(omap4_hwc_device_t *hwc_dev,
543                                    hwc_layer_t *layer,
544                                    IMG_native_handle_t *handle)
545{
546    /* Skip layers are handled by SF */
547    if ((layer->flags & HWC_SKIP_LAYER) || !handle)
548        return 0;
549
550    if (!omap4_hwc_is_valid_format(handle->iFormat))
551        return 0;
552
553    /* 1D buffers: no transform, must fit in TILER slot */
554    if (!is_NV12(handle->iFormat)) {
555        if (layer->transform)
556            return 0;
557        if (mem1d(handle) > MAX_TILER_SLOT)
558            return 0;
559    }
560
561    return omap4_hwc_can_scale_layer(hwc_dev, layer, handle);
562}
563
564struct counts {
565    unsigned int possible_overlay_layers;
566    unsigned int composited_layers;
567    unsigned int scaled_layers;
568    unsigned int RGB;
569    unsigned int BGR;
570    unsigned int NV12;
571    unsigned int displays;
572    unsigned int max_hw_overlays;
573    unsigned int max_scaling_overlays;
574    unsigned int mem;
575};
576
577static inline int can_dss_render_all(omap4_hwc_device_t *hwc_dev, struct counts *num)
578{
579    int tv = hwc_dev->ext & EXT_TV;
580    int nonscaling_ovls = NUM_NONSCALING_OVERLAYS;
581    int tform = hwc_dev->ext & EXT_TRANSFORM;
582    num->max_hw_overlays = MAX_HW_OVERLAYS;
583
584    /*
585     * We cannot atomically switch overlays from one display to another.  First, they
586     * have to be disabled, and the disabling has to take effect on the current display.
587     * We keep track of the available number of overlays here.
588     */
589    if (hwc_dev->ext & EXT_DOCK) {
590        /* some overlays may already be used by the external display, so we account for this */
591
592        /* reserve just a video pipeline for HDMI if docking */
593        hwc_dev->ext_ovls = num->NV12 ? 1 : 0;
594        num->max_hw_overlays -= max(hwc_dev->ext_ovls, hwc_dev->last_ext_ovls);
595    } else if (hwc_dev->ext) {
596        /*
597         * otherwise, manage just from half the pipelines.  NOTE: there is
598         * no danger of having used too many overlays for external display here.
599         */
600        num->max_hw_overlays >>= 1;
601        nonscaling_ovls >>= 1;
602        hwc_dev->ext_ovls = MAX_HW_OVERLAYS - num->max_hw_overlays;
603    } else {
604        num->max_hw_overlays -= hwc_dev->last_ext_ovls;
605        hwc_dev->ext_ovls = 0;
606    }
607
608    /*
609     * :TRICKY: We may not have enough overlays on the external display.  We "reserve" them
610     * here to figure out if mirroring is supported, but may not do mirroring for the first
611     * frame while the overlays required for it are cleared.
612     */
613    hwc_dev->ext_ovls = min(MAX_HW_OVERLAYS - hwc_dev->last_int_ovls, hwc_dev->ext_ovls);
614
615    /* if not docking, we may be limited by last used external overlays */
616    if (hwc_dev->ext_ovls && hwc_dev->ext && !(hwc_dev->ext & EXT_DOCK))
617         num->max_hw_overlays = hwc_dev->ext_ovls;
618
619    num->max_scaling_overlays = num->max_hw_overlays - nonscaling_ovls;
620
621    return  /* must have at least one layer if using composition bypass to get sync object */
622            num->possible_overlay_layers &&
623            num->possible_overlay_layers <= num->max_hw_overlays &&
624            num->possible_overlay_layers == num->composited_layers &&
625            num->scaled_layers <= num->max_scaling_overlays &&
626            /* fits into TILER slot */
627            num->mem <= MAX_TILER_SLOT &&
628            /* we cannot clone non-NV12 transformed layers */
629            (!tform || num->NV12 == num->possible_overlay_layers) &&
630            /* HDMI cannot display BGR */
631            (num->BGR == 0 || (num->RGB == 0 && !tv) || !hwc_dev->flags_rgb_order);
632}
633
634static inline int can_dss_render_layer(omap4_hwc_device_t *hwc_dev,
635            hwc_layer_t *layer)
636{
637    IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
638
639    int tv = hwc_dev->ext & EXT_TV;
640    int tform = hwc_dev->ext & EXT_TRANSFORM;
641
642    return omap4_hwc_is_valid_layer(hwc_dev, layer, handle) &&
643           /* cannot rotate non-NV12 layers on external display */
644           (!hwc_dev->ext || (hwc_dev->ext & EXT_DOCK) || !tform || is_NV12(handle->iFormat)) &&
645           /* skip non-NV12 layers if also using SGX (if nv12_only flag is set) */
646           (!hwc_dev->flags_nv12_only || (!hwc_dev->use_sgx || is_NV12(handle->iFormat))) &&
647           /* make sure RGB ordering is consistent (if rgb_order flag is set) */
648           (!(hwc_dev->swap_rb ? is_RGB(handle->iFormat) : is_BGR(handle->iFormat)) ||
649            !hwc_dev->flags_rgb_order) &&
650           /* TV can only render RGB */
651           !(tv && is_BGR(handle->iFormat)) &&
652           /* we can only rotate TILER2D buffers for external displays */
653           !(tform && !is_NV12(handle->iFormat));
654}
655
656static int omap4_hwc_prepare(struct hwc_composer_device *dev, hwc_layer_list_t* list)
657{
658    omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev;
659    struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->dsscomp_data;
660    struct counts num = { .composited_layers = list ? list->numHwLayers : 0 };
661    unsigned int i;
662
663    pthread_mutex_lock(&hwc_dev->lock);
664    memset(dsscomp, 0x0, sizeof(*dsscomp));
665    dsscomp->sync_id = sync_id++;
666
667    /* Figure out how many layers we can support via DSS */
668    for (i = 0; list && i < list->numHwLayers; i++) {
669        hwc_layer_t *layer = &list->hwLayers[i];
670        IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
671
672        layer->compositionType = HWC_FRAMEBUFFER;
673
674        if (omap4_hwc_is_valid_layer(hwc_dev, layer, handle)) {
675            num.possible_overlay_layers++;
676
677            /* NV12 layers can only be rendered on scaling overlays */
678            if (scaled(layer) || is_NV12(handle->iFormat))
679                num.scaled_layers++;
680
681            if (is_BGR(handle->iFormat))
682                num.BGR++;
683            else if (is_RGB(handle->iFormat))
684                num.RGB++;
685            else if (is_NV12(handle->iFormat))
686                num.NV12++;
687
688            num.mem += mem1d(handle);
689        }
690    }
691
692    /* phase 3 logic */
693    if (can_dss_render_all(hwc_dev, &num)) {
694        /* All layers can be handled by the DSS -- don't use SGX for composition */
695        hwc_dev->use_sgx = 0;
696        hwc_dev->swap_rb = num.BGR != 0;
697    } else {
698        /* Use SGX for composition plus first 3 layers that are DSS renderable */
699        hwc_dev->use_sgx = 1;
700        hwc_dev->swap_rb = is_BGR(hwc_dev->fb_dev->base.format);
701    }
702    if (debug) {
703        LOGD("prepare (%d) - %s (comp=%d, poss=%d/%d scaled, RGB=%d,BGR=%d,NV12=%d) (ext=%x, %dex/%dmx (last %dex,%din)\n",
704         dsscomp->sync_id,
705         hwc_dev->use_sgx ? "SGX+OVL" : "all-OVL",
706         num.composited_layers,
707         num.possible_overlay_layers, num.scaled_layers,
708         num.RGB, num.BGR, num.NV12,
709         hwc_dev->ext, hwc_dev->ext_ovls, num.max_hw_overlays, hwc_dev->last_ext_ovls, hwc_dev->last_int_ovls);
710    }
711
712    /* setup pipes */
713    dsscomp->num_ovls = hwc_dev->use_sgx;
714    int z = 0;
715    int fb_z = -1;
716    int scaled_gfx = 0;
717    int ix_nv12 = -1;
718
719    /* set up if DSS layers */
720    unsigned int mem_used = 0;
721    for (i = 0; list && i < list->numHwLayers; i++) {
722        hwc_layer_t *layer = &list->hwLayers[i];
723        IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
724
725        if (dsscomp->num_ovls < num.max_hw_overlays &&
726            can_dss_render_layer(hwc_dev, layer) &&
727            mem_used + mem1d(handle) < MAX_TILER_SLOT &&
728            /* can't have a transparent overlay in the middle of the framebuffer stack */
729            !(is_BLENDED(layer->blending) && fb_z >= 0)) {
730            /* render via DSS overlay */
731            mem_used += mem1d(handle);
732            layer->compositionType = HWC_OVERLAY;
733            hwc_dev->buffers[dsscomp->num_ovls] = layer->handle;
734
735            omap4_hwc_setup_layer(hwc_dev,
736                                  &dsscomp->ovls[dsscomp->num_ovls],
737                                  &list->hwLayers[i],
738                                  z,
739                                  handle->iFormat,
740                                  handle->iWidth,
741                                  handle->iHeight);
742
743            dsscomp->ovls[dsscomp->num_ovls].cfg.ix = dsscomp->num_ovls;
744            /* just marking dss layers */
745            dsscomp->ovls[dsscomp->num_ovls].address = (void *) (dsscomp->num_ovls * 4096 + 0xA0000000);
746            dsscomp->ovls[dsscomp->num_ovls].uv = (__u32) hwc_dev->buffers[dsscomp->num_ovls];
747
748            /* ensure GFX layer is never scaled */
749            if (dsscomp->num_ovls == 0) {
750                scaled_gfx = scaled(layer) || is_NV12(handle->iFormat);
751            } else if (scaled_gfx && !scaled(layer) && !is_NV12(handle->iFormat)) {
752                /* swap GFX layer with this one */
753                dsscomp->ovls[dsscomp->num_ovls].cfg.ix = 0;
754                dsscomp->ovls[0].cfg.ix = dsscomp->num_ovls;
755                scaled_gfx = 0;
756            }
757
758            /* remember first NV12 layer */
759            if (is_NV12(handle->iFormat) && ix_nv12 < 0)
760                ix_nv12 = dsscomp->num_ovls;
761
762            dsscomp->num_ovls++;
763            z++;
764        } else if (hwc_dev->use_sgx) {
765            if (fb_z < 0) {
766                /* NOTE: we are not handling transparent cutout for now */
767                fb_z = z;
768                z++;
769            } else {
770                /* move fb z-order up (by lowering dss layers) */
771                while (fb_z < z - 1)
772                    dsscomp->ovls[1 + fb_z++].cfg.zorder--;
773            }
774        }
775    }
776
777    /* clear FB above all opaque layers if rendering via SGX */
778    if (hwc_dev->use_sgx) {
779        for (i = 0; list && i < list->numHwLayers; i++) {
780            hwc_layer_t *layer = &list->hwLayers[i];
781            IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
782            if (layer->compositionType == HWC_FRAMEBUFFER)
783                continue;
784            if ((layer->flags & HWC_SKIP_LAYER) || !layer->handle)
785                continue;
786            if (!is_BLENDED(layer->blending))
787                layer->hints |= HWC_HINT_CLEAR_FB;
788        }
789    }
790
791    /* if scaling GFX (e.g. only 1 scaled surface) use a VID pipe */
792    if (scaled_gfx)
793        dsscomp->ovls[0].cfg.ix = 1;
794
795    /* assign a z-layer for fb */
796    if (hwc_dev->use_sgx && fb_z < 0) {
797        fb_z = z;
798        z++;
799    }
800
801    if (hwc_dev->use_sgx) {
802        hwc_dev->buffers[0] = NULL;
803        omap4_hwc_setup_layer_base(&dsscomp->ovls[0].cfg, fb_z,
804                                   hwc_dev->fb_dev->base.format,
805                                   hwc_dev->fb_dev->base.width,
806                                   hwc_dev->fb_dev->base.height);
807        dsscomp->ovls[0].cfg.pre_mult_alpha = 1;
808        dsscomp->ovls[0].uv = (__u32) hwc_dev->buffers[0];
809    }
810
811    /* mirror layers */
812    hwc_dev->post2_layers = dsscomp->num_ovls;
813    if (hwc_dev->ext && hwc_dev->ext_ovls) {
814        int ix_back, ix_front, ix;
815        if (hwc_dev->ext & EXT_DOCK) {
816            /* mirror only NV12 layer */
817            ix_back = ix_front = ix_nv12;
818        } else {
819            /* mirror all layers */
820            ix_back = 0;
821            ix_front = dsscomp->num_ovls - 1;
822        }
823
824        for (ix = ix_back; ix >= 0 && ix <= ix_front; ix++) {
825            memcpy(dsscomp->ovls + dsscomp->num_ovls, dsscomp->ovls + ix, sizeof(dsscomp->ovls[ix]));
826            dsscomp->ovls[dsscomp->num_ovls].cfg.zorder += hwc_dev->post2_layers;
827
828            /* reserve overlays at end for other display */
829            dsscomp->ovls[dsscomp->num_ovls].cfg.ix = MAX_HW_OVERLAYS - 1 - (ix - ix_back);
830            dsscomp->ovls[dsscomp->num_ovls].cfg.mgr_ix = 1;
831            dsscomp->ovls[dsscomp->num_ovls].ba = ix;
832
833            if (hwc_dev->ext & EXT_DOCK) {
834                /* full screen video */
835                dsscomp->ovls[dsscomp->num_ovls].cfg.win.x = 0;
836                dsscomp->ovls[dsscomp->num_ovls].cfg.win.y = 0;
837                set_ext_matrix(hwc_dev, dsscomp->ovls[dsscomp->num_ovls].cfg.win.w,
838                               dsscomp->ovls[dsscomp->num_ovls].cfg.win.h);
839            }
840            omap4_hwc_adjust_ext_layer(hwc_dev, dsscomp->ovls + dsscomp->num_ovls);
841            dsscomp->num_ovls++;
842            z++;
843        }
844    }
845
846    if (z != dsscomp->num_ovls || dsscomp->num_ovls > MAX_HW_OVERLAYS)
847        LOGE("**** used %d z-layers for %d overlays\n", z, dsscomp->num_ovls);
848
849    dsscomp->mode = DSSCOMP_SETUP_DISPLAY;
850    dsscomp->mgrs[0].ix = 0;
851    dsscomp->mgrs[0].alpha_blending = 1;
852    dsscomp->mgrs[0].swap_rb = hwc_dev->swap_rb;
853    dsscomp->num_mgrs = 1;
854
855    if (hwc_dev->ext || hwc_dev->last_ext_ovls) {
856        dsscomp->mgrs[1] = dsscomp->mgrs[0];
857        dsscomp->mgrs[1].ix = 1;
858        dsscomp->num_mgrs++;
859        hwc_dev->ext_ovls = dsscomp->num_ovls - hwc_dev->post2_layers;
860    }
861    pthread_mutex_unlock(&hwc_dev->lock);
862    return 0;
863}
864
865static int omap4_hwc_set(struct hwc_composer_device *dev, hwc_display_t dpy,
866               hwc_surface_t sur, hwc_layer_list_t* list)
867{
868    omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev;
869    struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->dsscomp_data;
870    int err = 0;
871    unsigned int i;
872
873    pthread_mutex_lock(&hwc_dev->lock);
874    char big_log[1024];
875    int e = sizeof(big_log);
876    char *end = big_log + e;
877    e -= snprintf(end - e, e, "set H{");
878    for (i = 0; list && i < list->numHwLayers; i++) {
879        if (i)
880            e -= snprintf(end - e, e, " ");
881        hwc_layer_t *layer = &list->hwLayers[i];
882        IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
883        e -= snprintf(end - e, e, "%p:%s,", handle, layer->compositionType == HWC_OVERLAY ? "DSS" : "SGX");
884        if ((layer->flags & HWC_SKIP_LAYER) || !handle) {
885            e -= snprintf(end - e, e, "SKIP");
886            continue;
887        }
888        if (layer->flags & HWC_HINT_CLEAR_FB)
889            e -= snprintf(end - e, e, "CLR,");
890#define FMT(f) ((f) == HAL_PIXEL_FORMAT_TI_NV12 ? "NV12" : \
891                (f) == HAL_PIXEL_FORMAT_BGRX_8888 ? "xRGB32" : \
892                (f) == HAL_PIXEL_FORMAT_RGBX_8888 ? "xBGR32" : \
893                (f) == HAL_PIXEL_FORMAT_BGRA_8888 ? "ARGB32" : \
894                (f) == HAL_PIXEL_FORMAT_RGBA_8888 ? "ABGR32" : \
895                (f) == HAL_PIXEL_FORMAT_RGB_565 ? "RGB565" : "??")
896        e -= snprintf(end - e, e, "%d*%d(%s)", handle->iWidth, handle->iHeight, FMT(handle->iFormat));
897        if (layer->transform)
898            e -= snprintf(end - e, e, "~%d", layer->transform);
899#undef FMT
900    }
901    e -= snprintf(end - e, e, "} D{");
902    for (i = 0; i < dsscomp->num_ovls; i++) {
903        if (i)
904            e -= snprintf(end - e, e, " ");
905        e -= snprintf(end - e, e, "%d=", dsscomp->ovls[i].cfg.ix);
906#define FMT(f) ((f) == OMAP_DSS_COLOR_NV12 ? "NV12" : \
907                (f) == OMAP_DSS_COLOR_RGB24U ? "xRGB32" : \
908                (f) == OMAP_DSS_COLOR_ARGB32 ? "ARGB32" : \
909                (f) == OMAP_DSS_COLOR_RGB16 ? "RGB565" : "??")
910        if (dsscomp->ovls[i].cfg.enabled)
911            e -= snprintf(end - e, e, "%08x:%d*%d,%s",
912                          dsscomp->ovls[i].ba,
913                          dsscomp->ovls[i].cfg.width,
914                          dsscomp->ovls[i].cfg.height,
915                          FMT(dsscomp->ovls[i].cfg.color_mode));
916#undef FMT
917        else
918            e -= snprintf(end - e, e, "-");
919    }
920    e -= snprintf(end - e, e, "} L{");
921    for (i = 0; i < hwc_dev->post2_layers; i++) {
922        if (i)
923            e -= snprintf(end - e, e, " ");
924        e -= snprintf(end - e, e, "%p", hwc_dev->buffers[i]);
925    }
926    e -= snprintf(end - e, e, "}%s\n", hwc_dev->use_sgx ? " swap" : "");
927    if (debug) {
928        LOGD("%s", big_log);
929    }
930
931    // LOGD("set %d layers (sgx=%d)\n", dsscomp->num_ovls, hwc_dev->use_sgx);
932
933    if (dpy && sur) {
934        // list can be NULL which means hwc is temporarily disabled.
935        // however, if dpy and sur are null it means we're turning the
936        // screen off. no shall not call eglSwapBuffers() in that case.
937
938        if (hwc_dev->use_sgx) {
939            if (!eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur)) {
940                LOGE("eglSwapBuffers error");
941                err = HWC_EGL_ERROR;
942                goto err_out;
943            }
944        }
945
946        //dump_dsscomp(dsscomp);
947
948        err = hwc_dev->fb_dev->Post2((framebuffer_device_t *)hwc_dev->fb_dev,
949                                 hwc_dev->buffers,
950                                 hwc_dev->post2_layers,
951                                 dsscomp, sizeof(*dsscomp));
952
953        if (!hwc_dev->use_sgx) {
954            __u32 crt = 0;
955            int err2 = ioctl(hwc_dev->fb_fd, FBIO_WAITFORVSYNC, &crt);
956            if (err2) {
957                LOGE("failed to wait for vsync (%d)", errno);
958                err = err ? : -errno;
959            }
960        }
961    }
962    hwc_dev->last_ext_ovls = hwc_dev->ext_ovls;
963    hwc_dev->last_int_ovls = hwc_dev->post2_layers;
964    if (err)
965        LOGE("Post2 error");
966
967err_out:
968    pthread_mutex_unlock(&hwc_dev->lock);
969    return err;
970}
971
972static int dump_printf(char *buff, int buff_len, int len, const char *fmt, ...)
973{
974    va_list ap;
975
976    int print_len;
977
978    va_start(ap, fmt);
979
980    print_len = vsnprintf(buff + len, buff_len - len, fmt, ap);
981
982    va_end(ap);
983
984    return len + print_len;
985}
986
987static void omap4_hwc_dump(struct hwc_composer_device *dev, char *buff, int buff_len)
988{
989    omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev;
990    struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->dsscomp_data;
991    int len = 0;
992    int i;
993
994    len = dump_printf(buff, buff_len, len, "omap4_hwc %d:\n", dsscomp->num_ovls);
995
996    for (i = 0; i < dsscomp->num_ovls; i++) {
997        struct dss2_ovl_cfg *cfg = &dsscomp->ovls[i].cfg;
998
999        len = dump_printf(buff, buff_len, len, "  layer %d:\n", i);
1000        len = dump_printf(buff, buff_len, len, "     enabled: %s\n",
1001                          cfg->enabled ? "true" : "false");
1002        len = dump_printf(buff, buff_len, len, "     buff: %dx%d stride: %d:\n",
1003                          cfg->width, cfg->height, cfg->stride);
1004        len = dump_printf(buff, buff_len, len, "     src: (%d,%d) %dx%d\n",
1005                          cfg->crop.x, cfg->crop.y, cfg->crop.w, cfg->crop.h);
1006        len = dump_printf(buff, buff_len, len, "     dst: (%d,%d) %dx%d\n",
1007                          cfg->win.x, cfg->win.y, cfg->win.w, cfg->win.h);
1008        len = dump_printf(buff, buff_len, len, "     ix: %d\n", cfg->ix);
1009        len = dump_printf(buff, buff_len, len, "     zorder: %d\n\n", cfg->zorder);
1010    }
1011}
1012
1013
1014static int omap4_hwc_device_close(hw_device_t* device)
1015{
1016    omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) device;;
1017
1018    if (hwc_dev) {
1019        if (hwc_dev->dsscomp_fd >= 0)
1020            close(hwc_dev->dsscomp_fd);
1021        if (hwc_dev->hdmi_fb_fd >= 0)
1022            close(hwc_dev->hdmi_fb_fd);
1023        if (hwc_dev->fb_fd >= 0)
1024            close(hwc_dev->fb_fd);
1025        /* pthread will get killed when parent process exits */
1026        pthread_mutex_destroy(&hwc_dev->lock);
1027        free(hwc_dev);
1028    }
1029
1030    return 0;
1031}
1032
1033static int omap4_hwc_open_fb_hal(IMG_framebuffer_device_public_t **fb_dev)
1034{
1035    IMG_gralloc_module_public_t *psGrallocModule;
1036    int err;
1037
1038    err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
1039                        (const hw_module_t**)&psGrallocModule);
1040    if(err)
1041        goto err_out;
1042
1043    if(strcmp(psGrallocModule->base.common.author,
1044              "Imagination Technologies"))
1045    {
1046        err = -EINVAL;
1047        goto err_out;
1048    }
1049
1050    *fb_dev = psGrallocModule->psFrameBufferDevice;
1051
1052    return 0;
1053
1054err_out:
1055    LOGE("Composer HAL failed to load compatible Graphics HAL");
1056    return err;
1057}
1058
1059static void handle_hotplug(omap4_hwc_device_t *hwc_dev, int state)
1060{
1061    pthread_mutex_lock(&hwc_dev->lock);
1062    hwc_dev->ext = 0;
1063    if (state) {
1064        struct _qdis {
1065            struct dsscomp_display_info dis;
1066            struct dsscomp_videomode modedb[16];
1067        } d = { .dis = { .ix = 1 } };
1068        d.dis.modedb_len = sizeof(d.modedb) / sizeof(*d.modedb);
1069        int ret = ioctl(hwc_dev->dsscomp_fd, DSSCOMP_QUERY_DISPLAY, &d);
1070        if (!ret) {
1071            __u32 i, best = ~0, best_score = 0;
1072            hwc_dev->ext = EXT_ON | 3;
1073            hwc_dev->ext_width = d.dis.width_in_mm;
1074            hwc_dev->ext_height = d.dis.height_in_mm;
1075            hwc_dev->ext_xres = d.dis.timings.x_res;
1076            hwc_dev->ext_yres = d.dis.timings.y_res;
1077            for (i = 0; i < d.dis.modedb_len; i++) {
1078                __u32 score = 0;
1079                __u32 fb_xres = (hwc_dev->ext & 1) ? hwc_dev->fb_dev->base.height : hwc_dev->fb_dev->base.width;
1080                __u32 fb_yres = (hwc_dev->ext & 1) ? hwc_dev->fb_dev->base.width : hwc_dev->fb_dev->base.height;
1081                __u32 fb_area = fb_xres * fb_yres;
1082                __u32 mode_area = d.modedb[i].xres * d.modedb[i].yres;
1083                __u32 ext_width = d.dis.width_in_mm;
1084                __u32 ext_height = d.dis.height_in_mm;
1085                __u32 ext_fb_xres, ext_fb_yres;
1086
1087                if (d.modedb[i].flag & FB_FLAG_RATIO_4_3) {
1088                    ext_width = 4;
1089                    ext_height = 3;
1090                } else if (d.modedb[i].flag & FB_FLAG_RATIO_16_9) {
1091                    ext_width = 16;
1092                    ext_height = 9;
1093                }
1094
1095                get_max_dimensions(fb_xres, fb_yres, 1, 1, d.modedb[i].xres, d.modedb[i].yres,
1096                                   ext_width, ext_height, &ext_fb_xres, &ext_fb_yres);
1097
1098                if (!omap4_hwc_can_scale(fb_xres, fb_yres, ext_fb_xres, ext_fb_yres,
1099                                         hwc_dev->ext & EXT_TRANSFORM, &d.dis, &limits))
1100                    continue;
1101
1102                /* prefer CEA modes */
1103                if (d.modedb[i].flag & (FB_FLAG_RATIO_4_3 | FB_FLAG_RATIO_16_9))
1104                    score |= (1 << 30);
1105
1106                /* prefer to upscale (1% tolerance) */
1107                if (ext_fb_xres >= fb_xres * 99 / 100 && ext_fb_yres >= fb_yres * 99 / 100)
1108                    score |= (1 << 29);
1109
1110                /* pick smallest leftover area */
1111                score |= (1 << 24) * ((16 * ext_fb_xres * ext_fb_yres + (mode_area >> 1)) / mode_area);
1112
1113                /* pick closest screen size */
1114                if (ext_fb_xres * ext_fb_yres > fb_area)
1115                    score |= (1 << 19) * (16 * fb_area / ext_fb_xres / ext_fb_yres);
1116                else
1117                    score |= (1 << 19) * (16 * ext_fb_xres * ext_fb_yres / fb_area);
1118
1119                /* pick highest frame rate */
1120                score |= (1 << 11) * d.modedb[i].refresh;
1121
1122                LOGD("#%d: %dx%d %dHz", i, d.modedb[i].xres, d.modedb[i].yres, d.modedb[i].refresh);
1123                if (debug)
1124                    LOGD("  score=%u adj.res=%dx%d", score, ext_fb_xres, ext_fb_yres);
1125                if (best_score < score) {
1126                    hwc_dev->ext_width = ext_width;
1127                    hwc_dev->ext_height = ext_height;
1128                    hwc_dev->ext_xres = d.modedb[i].xres;
1129                    hwc_dev->ext_yres = d.modedb[i].yres;
1130                    best = i;
1131                    best_score = score;
1132                }
1133            }
1134            if (~best) {
1135                struct dsscomp_setup_display_data sdis = { .ix = 1, };
1136                sdis.mode = d.dis.modedb[best];
1137                LOGD("picking #%d", best);
1138                ioctl(hwc_dev->dsscomp_fd, DSSCOMP_SETUP_DISPLAY, &sdis);
1139            } else {
1140                __u32 fb_xres = (hwc_dev->ext & 1) ? hwc_dev->fb_dev->base.height : hwc_dev->fb_dev->base.width;
1141                __u32 fb_yres = (hwc_dev->ext & 1) ? hwc_dev->fb_dev->base.width : hwc_dev->fb_dev->base.height;
1142                __u32 ext_width = d.dis.width_in_mm;
1143                __u32 ext_height = d.dis.height_in_mm;
1144                __u32 ext_fb_xres, ext_fb_yres;
1145
1146                get_max_dimensions(fb_xres, fb_yres, 1, 1, d.dis.timings.x_res, d.dis.timings.y_res,
1147                                   ext_width, ext_height, &ext_fb_xres, &ext_fb_yres);
1148                if (!omap4_hwc_can_scale(fb_xres, fb_yres, ext_fb_xres, ext_fb_yres,
1149                                         hwc_dev->ext & EXT_TRANSFORM, &d.dis, &limits)) {
1150                    LOGE("DSS scaler cannot support HDMI cloning");
1151                    hwc_dev->ext = 0;
1152                }
1153            }
1154
1155            if (hwc_dev->ext) {
1156                if (d.dis.channel == OMAP_DSS_CHANNEL_DIGIT)
1157                    hwc_dev->ext |= EXT_TV;
1158                ioctl(hwc_dev->hdmi_fb_fd, FBIOBLANK, FB_BLANK_UNBLANK);
1159            }
1160        }
1161
1162        /* FIXME set up hwc_dev->ext based on mirroring needs */
1163        char value[PROPERTY_VALUE_MAX];
1164        property_get("debug.hwc.ext", value, "0");
1165        hwc_dev->ext |= atoi(value) & EXT_DOCK;
1166    }
1167    omap4_hwc_create_ext_matrix(hwc_dev);
1168    LOGI("external display changed (state=%d, on=%d, dock=%d, tv=%d, trform=%ddeg%s)", state,
1169         !!hwc_dev->ext, !!(hwc_dev->ext & EXT_DOCK),
1170         !!(hwc_dev->ext & EXT_TV), hwc_dev->ext & EXT_ROTATION,
1171         (hwc_dev->ext & EXT_HFLIP) ? "+hflip" : "");
1172    pthread_mutex_unlock(&hwc_dev->lock);
1173
1174    if (hwc_dev->procs && hwc_dev->procs->invalidate) {
1175            hwc_dev->procs->invalidate(hwc_dev->procs);
1176            usleep(30000);
1177            hwc_dev->procs->invalidate(hwc_dev->procs);
1178    }
1179}
1180
1181static void handle_uevents(omap4_hwc_device_t *hwc_dev, const char *s)
1182{
1183    if (strcmp(s, "change@/devices/virtual/switch/hdmi"))
1184        return;
1185
1186    s += strlen(s) + 1;
1187
1188    while(*s) {
1189        if (!strncmp(s, "SWITCH_STATE=", strlen("SWITCH_STATE="))) {
1190            int state = atoi(s + strlen("SWITCH_STATE="));
1191            handle_hotplug(hwc_dev, state);
1192        }
1193
1194        s += strlen(s) + 1;
1195    }
1196}
1197
1198static void *omap4_hwc_hdmi_thread(void *data)
1199{
1200    omap4_hwc_device_t *hwc_dev = data;
1201    static char uevent_desc[4096];
1202    uevent_init();
1203
1204    memset(uevent_desc, 0, sizeof(uevent_desc));
1205
1206    do {
1207        /* keep last 2 zeroes to ensure double 0 termination */
1208        uevent_next_event(uevent_desc, sizeof(uevent_desc) - 2);
1209        handle_uevents(hwc_dev, uevent_desc);
1210    } while (1);
1211
1212    return NULL;
1213}
1214
1215static void omap4_hwc_registerProcs(struct hwc_composer_device* dev,
1216                                    hwc_procs_t const* procs)
1217{
1218        omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) dev;
1219
1220        hwc_dev->procs = (typeof(hwc_dev->procs)) procs;
1221}
1222
1223static int omap4_hwc_device_open(const hw_module_t* module, const char* name,
1224                hw_device_t** device)
1225{
1226    omap4_hwc_module_t *hwc_mod = (omap4_hwc_module_t *)module;
1227    omap4_hwc_device_t *hwc_dev;
1228    int err = 0;
1229
1230    if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
1231        return -EINVAL;
1232    }
1233
1234    if (!hwc_mod->fb_dev) {
1235        err = omap4_hwc_open_fb_hal(&hwc_mod->fb_dev);
1236        if (err)
1237            return err;
1238
1239        if (!hwc_mod->fb_dev) {
1240            LOGE("Framebuffer HAL not opened before HWC");
1241            return -EFAULT;
1242        }
1243        hwc_mod->fb_dev->bBypassPost = 1;
1244    }
1245
1246    hwc_dev = (omap4_hwc_device_t *)malloc(sizeof(*hwc_dev));
1247    if (hwc_dev == NULL)
1248        return -ENOMEM;
1249
1250    memset(hwc_dev, 0, sizeof(*hwc_dev));
1251
1252    hwc_dev->base.common.tag = HARDWARE_DEVICE_TAG;
1253    hwc_dev->base.common.version = HWC_API_VERSION;
1254    hwc_dev->base.common.module = (hw_module_t *)module;
1255    hwc_dev->base.common.close = omap4_hwc_device_close;
1256    hwc_dev->base.prepare = omap4_hwc_prepare;
1257    hwc_dev->base.set = omap4_hwc_set;
1258    hwc_dev->base.dump = omap4_hwc_dump;
1259    hwc_dev->base.registerProcs = omap4_hwc_registerProcs;
1260    hwc_dev->fb_dev = hwc_mod->fb_dev;
1261    *device = &hwc_dev->base.common;
1262
1263    hwc_dev->dsscomp_fd = open("/dev/dsscomp", O_RDWR);
1264    if (hwc_dev->dsscomp_fd < 0) {
1265        LOGE("failed to open dsscomp (%d)", errno);
1266        err = -errno;
1267        goto done;
1268    }
1269
1270    hwc_dev->hdmi_fb_fd = open("/dev/graphics/fb1", O_RDWR);
1271    if (hwc_dev->hdmi_fb_fd < 0) {
1272        LOGE("failed to open hdmi fb (%d)", errno);
1273        err = -errno;
1274        goto done;
1275    }
1276
1277    hwc_dev->fb_fd = open("/dev/graphics/fb0", O_RDWR);
1278    if (hwc_dev->fb_fd < 0) {
1279        LOGE("failed to open fb (%d)", errno);
1280        err = -errno;
1281        goto done;
1282    }
1283
1284    hwc_dev->buffers = malloc(sizeof(buffer_handle_t) * MAX_HW_OVERLAYS);
1285    if (!hwc_dev->buffers) {
1286        err = -ENOMEM;
1287        goto done;
1288    }
1289
1290    int ret = ioctl(hwc_dev->dsscomp_fd, DSSCOMP_QUERY_DISPLAY, &hwc_dev->fb_dis);
1291    if (ret) {
1292        LOGE("failed to get display info (%d): %m", errno);
1293        err = -errno;
1294        goto done;
1295    }
1296
1297    if (pthread_mutex_init(&hwc_dev->lock, NULL)) {
1298            LOGE("failed to create mutex (%d): %m", errno);
1299            err = -errno;
1300            goto done;
1301    }
1302    if (pthread_create(&hwc_dev->hdmi_thread, NULL, omap4_hwc_hdmi_thread, hwc_dev))
1303    {
1304            LOGE("failed to create HDMI listening thread (%d): %m", errno);
1305            err = -errno;
1306            goto done;
1307    }
1308
1309    /* get debug properties */
1310
1311    /* see if hwc is enabled at all */
1312    char value[PROPERTY_VALUE_MAX];
1313    property_get("debug.hwc.rgb_order", value, "1");
1314    hwc_dev->flags_rgb_order = atoi(value);
1315    property_get("debug.hwc.nv12_only", value, "0");
1316    hwc_dev->flags_nv12_only = atoi(value);
1317
1318    /* read switch state */
1319    int sw_fd = open("/sys/class/switch/hdmi/state", O_RDONLY);
1320    int hpd = 0;
1321    if (sw_fd >= 0) {
1322        char value;
1323        if (read(sw_fd, &value, 1) == 1)
1324            hpd = value == '1';
1325        close(sw_fd);
1326    }
1327    handle_hotplug(hwc_dev, hpd);
1328
1329    LOGE("omap4_hwc_device_open(rgb_order=%d nv12_only=%d)",
1330        hwc_dev->flags_rgb_order, hwc_dev->flags_nv12_only);
1331
1332done:
1333    if (err && hwc_dev) {
1334        if (hwc_dev->dsscomp_fd >= 0)
1335            close(hwc_dev->dsscomp_fd);
1336        if (hwc_dev->hdmi_fb_fd >= 0)
1337            close(hwc_dev->hdmi_fb_fd);
1338        if (hwc_dev->fb_fd >= 0)
1339            close(hwc_dev->fb_fd);
1340        pthread_mutex_destroy(&hwc_dev->lock);
1341        free(hwc_dev->buffers);
1342        free(hwc_dev);
1343    }
1344
1345    return err;
1346}
1347
1348static struct hw_module_methods_t omap4_hwc_module_methods = {
1349    .open = omap4_hwc_device_open,
1350};
1351
1352omap4_hwc_module_t HAL_MODULE_INFO_SYM = {
1353    .base = {
1354        .common = {
1355            .tag =                  HARDWARE_MODULE_TAG,
1356            .version_major =        1,
1357            .version_minor =        0,
1358            .id =                   HWC_HARDWARE_MODULE_ID,
1359            .name =                 "OMAP 44xx Hardware Composer HAL",
1360            .author =               "Texas Instruments",
1361            .methods =              &omap4_hwc_module_methods,
1362        },
1363    },
1364};
1365