hwc.c revision 876331fc77f6763c8c390d1289ead00f89f8d9fe
1c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev/*
2c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * Copyright (C) Texas Instruments - http://www.ti.com/
3c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev *
4c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * Licensed under the Apache License, Version 2.0 (the "License");
5c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * you may not use this file except in compliance with the License.
6c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * You may obtain a copy of the License at
7c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev *
8c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev *      http://www.apache.org/licenses/LICENSE-2.0
9c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev *
10c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * Unless required by applicable law or agreed to in writing, software
11c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * distributed under the License is distributed on an "AS IS" BASIS,
12c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * See the License for the specific language governing permissions and
14c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * limitations under the License.
15c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev */
16c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
17c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include <errno.h>
18c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include <malloc.h>
19c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include <stdlib.h>
20c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include <stdarg.h>
212125fa148686edfa389121f946377aedaa3d9483Lajos Molnar#include <fcntl.h>
2202150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian#include <poll.h>
23751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen#include <sys/eventfd.h>
242125fa148686edfa389121f946377aedaa3d9483Lajos Molnar#include <sys/ioctl.h>
252125fa148686edfa389121f946377aedaa3d9483Lajos Molnar#include <linux/fb.h>
26e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian#include <linux/omapfb.h>
270aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar#include <sys/mman.h>
28e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian#include <sys/resource.h>
29c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
30c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include <cutils/properties.h>
31c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include <cutils/log.h>
32c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include <cutils/native_handle.h>
33876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen#define HWC_REMOVE_DEPRECATED_VERSIONS 0
34c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include <hardware/hardware.h>
35c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include <hardware/hwcomposer.h>
36c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include <EGL/egl.h>
372125fa148686edfa389121f946377aedaa3d9483Lajos Molnar#include <hardware_legacy/uevent.h>
380aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar#include <png.h>
39c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
40e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian#include <system/graphics.h>
41876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen#include <linux/bltsville.h>
42876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
43876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen#define MAX_HWC_LAYERS 32
44ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar
45e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian#define ASPECT_RATIO_TOLERANCE 0.02f
46a02dce1ac438e0538fbcef1c663092035c5f4348Lajos Molnar
4778fce72baff38f488a0117591d4241d278a48b1bLajos Molnar#define min(a, b) ( { typeof(a) __a = (a), __b = (b); __a < __b ? __a : __b; } )
4878fce72baff38f488a0117591d4241d278a48b1bLajos Molnar#define max(a, b) ( { typeof(a) __a = (a), __b = (b); __a > __b ? __a : __b; } )
49d4599029522592f46eccf9d57add7ebd7d23fdd1Lajos Molnar#define swap(a, b) do { typeof(a) __a = (a); (a) = (b); (b) = __a; } while (0)
5078fce72baff38f488a0117591d4241d278a48b1bLajos Molnar
512704d381ccfba0fe96e61cd368507506c3adfacaLajos Molnar#define WIDTH(rect) ((rect).right - (rect).left)
522704d381ccfba0fe96e61cd368507506c3adfacaLajos Molnar#define HEIGHT(rect) ((rect).bottom - (rect).top)
532704d381ccfba0fe96e61cd368507506c3adfacaLajos Molnar
5416b7f6c4b06ac7350c30309d0559a466097d8ae7Lajos Molnar#define DIV_ROUND_UP(a, b) (((a) + (b) - 1) / (b))
5516b7f6c4b06ac7350c30309d0559a466097d8ae7Lajos Molnar
56c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include <video/dsscomp.h>
57876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen#include <video/omap_hwc.h>
58c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
59c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include "hal_public.h"
60876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen#include "rgz_2d.h"
61c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
62c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#define MAX_HW_OVERLAYS 4
6378fce72baff38f488a0117591d4241d278a48b1bLajos Molnar#define NUM_NONSCALING_OVERLAYS 1
64b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar#define HAL_PIXEL_FORMAT_BGRX_8888      0x1FF
65b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar#define HAL_PIXEL_FORMAT_TI_NV12        0x100
66c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#define HAL_PIXEL_FORMAT_TI_NV12_PADDED 0x101
676d94b7785c5318b6de36193a7f5488a88b6178ebDandawate Saket#define MAX_TILER_SLOT (32 << 20)
68c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
69ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnarstruct ext_transform_t {
70ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    __u8 rotation : 3;          /* 90-degree clockwise rotations */
71ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    __u8 hflip    : 1;          /* flip l-r (after rotation) */
72ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    __u8 enabled  : 1;          /* cloning enabled */
73ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    __u8 docking  : 1;          /* docking vs. mirroring - used for state */
74ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar};
75ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar
76ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar/* cloning support and state */
77ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnarstruct omap4_hwc_ext {
78ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    /* support */
79ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    struct ext_transform_t mirror;      /* mirroring settings */
80ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    struct ext_transform_t dock;        /* docking settings */
813797fa989f5fee97caea2bbadf433a5a9ac03d8dLajos Molnar    float lcd_xpy;                      /* pixel ratio for UI */
824e635e537afaa9f1416fa5bdbfd1b03afd8b7e6aLajos Molnar    __u8 avoid_mode_change;             /* use HDMI mode used for mirroring if possible */
832b86fd0cbeb42123fc20b1f646ee81299e831d16Lajos Molnar    __u8 force_dock;                     /* must dock */
842b86fd0cbeb42123fc20b1f646ee81299e831d16Lajos Molnar    __u8 hdmi_state;                     /* whether HDMI is connected */
85ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar
86ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    /* state */
87ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    __u8 on_tv;                         /* using a tv */
88ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    struct ext_transform_t current;     /* current settings */
89ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    struct ext_transform_t last;        /* last-used settings */
90ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar
91ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    /* configuration */
921b24d08333d1f847e6211aaa1b81f5792aca2704Lajos Molnar    __u32 last_xres_used;               /* resolution and pixel ratio used for mode selection */
93ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    __u32 last_yres_used;
944cb51e55fa79a592d50d94c0700660e42c988a0bLajos Molnar    __u32 last_mode;                    /* 2-s complement of last HDMI mode set, 0 if none */
954e635e537afaa9f1416fa5bdbfd1b03afd8b7e6aLajos Molnar    __u32 mirror_mode;                  /* 2-s complement of mode used when mirroring */
961b24d08333d1f847e6211aaa1b81f5792aca2704Lajos Molnar    float last_xpy;
97ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    __u16 width;                        /* external screen dimensions */
98ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    __u16 height;
99ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    __u32 xres;                         /* external screen resolution */
100ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    __u32 yres;
101ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    float m[2][3];                      /* external transformation matrix */
1028d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    hwc_rect_t mirror_region;           /* region of screen to mirror */
103ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar};
104ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnartypedef struct omap4_hwc_ext omap4_hwc_ext_t;
105ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar
106ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar/* used by property settings */
10778fce72baff38f488a0117591d4241d278a48b1bLajos Molnarenum {
10878fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    EXT_ROTATION    = 3,        /* rotation while mirroring */
10978fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    EXT_HFLIP       = (1 << 2), /* flip l-r on output (after rotation) */
11078fce72baff38f488a0117591d4241d278a48b1bLajos Molnar};
11178fce72baff38f488a0117591d4241d278a48b1bLajos Molnar
112876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chenenum bltpolicy {
113876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    BLTPOLICY_DISABLED = 0,
114876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    BLTPOLICY_DEFAULT = 1,    /* Default blit policy */
115876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    BLTPOLICY_ALL,            /* Test mode to attempt to blit all */
116876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen};
117876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
118876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chenenum bltmode {
119876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    BLTMODE_PAINT = 0,    /* Attempt to blit layer by layer */
120876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    BLTMODE_REGION = 1,   /* Attempt to blit layers via regions */
121876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen};
122876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1230aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar/* ARGB image */
1240aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnarstruct omap4_hwc_img {
1250aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    int width;
1260aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    int height;
1270aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    int rowbytes;
1280aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    int size;
1290aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    unsigned char *ptr;
1300aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar} dock_image = { .rowbytes = 0 };
1310aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar
132c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstruct omap4_hwc_module {
133c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    hwc_module_t base;
134c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
135c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    IMG_framebuffer_device_public_t *fb_dev;
136c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev};
137c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevtypedef struct omap4_hwc_module omap4_hwc_module_t;
138c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
139c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstruct omap4_hwc_device {
14000d8485d3d319633f410e52cab1562fe165af1e3Lajos Molnar    /* static data */
1416ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden    hwc_composer_device_1_t base;
1422125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    hwc_procs_t *procs;
1432125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    pthread_t hdmi_thread;
1442125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    pthread_mutex_t lock;
145c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
146c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    IMG_framebuffer_device_public_t *fb_dev;
147d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar    struct dsscomp_display_info fb_dis;
14800d8485d3d319633f410e52cab1562fe165af1e3Lajos Molnar    int fb_fd;                  /* file descriptor for /dev/fb0 */
14900d8485d3d319633f410e52cab1562fe165af1e3Lajos Molnar    int dsscomp_fd;             /* file descriptor for /dev/dsscomp */
15000d8485d3d319633f410e52cab1562fe165af1e3Lajos Molnar    int hdmi_fb_fd;             /* file descriptor for /dev/fb1 */
151751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    int wakeup_evt;             /* eventfd used to wakeup event thread */
15200d8485d3d319633f410e52cab1562fe165af1e3Lajos Molnar
1530aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    int img_mem_size;           /* size of fb for hdmi */
1540aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    void *img_mem_ptr;          /* start of fb for hdmi */
1550aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar
15600d8485d3d319633f410e52cab1562fe165af1e3Lajos Molnar    int flags_rgb_order;
15700d8485d3d319633f410e52cab1562fe165af1e3Lajos Molnar    int flags_nv12_only;
158c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
159876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    int on_tv;                  /* using a tv */
16000d8485d3d319633f410e52cab1562fe165af1e3Lajos Molnar    int force_sgx;
16100d8485d3d319633f410e52cab1562fe165af1e3Lajos Molnar    omap4_hwc_ext_t ext;        /* external mirroring data */
16200d8485d3d319633f410e52cab1562fe165af1e3Lajos Molnar    int idle;
16300d8485d3d319633f410e52cab1562fe165af1e3Lajos Molnar    int ovls_blending;
164ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar
165876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    float primary_m[2][3];          /* internal transformation matrix */
166876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    int primary_transform;
167876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    int primary_rotation;
168876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    hwc_rect_t primary_region;
1695db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket
170c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    buffer_handle_t *buffers;
171c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    int use_sgx;
17278fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    int swap_rb;
173876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    unsigned int post2_layers; /* Buffers used with DSS pipes*/
174876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    unsigned int post2_blit_buffers; /* Buffers used with blit */
17500d8485d3d319633f410e52cab1562fe165af1e3Lajos Molnar    int ext_ovls;               /* # of overlays on external display for current composition */
17600d8485d3d319633f410e52cab1562fe165af1e3Lajos Molnar    int ext_ovls_wanted;        /* # of overlays that should be on external display for current composition */
17700d8485d3d319633f410e52cab1562fe165af1e3Lajos Molnar    int last_ext_ovls;          /* # of overlays on external/internal display for last composition */
17878fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    int last_int_ovls;
179876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
180876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    enum bltmode blt_mode;
181876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    enum bltpolicy blt_policy;
182876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
183876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    int blit_flags;
184876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    int blit_num;
185876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    struct omap_hwc_data comp_data; /* This is a kernel data structure */
186876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    struct rgz_blt_entry blit_ops[RGZ_MAX_BLITS];
187751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
188751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    /* fake vsync event state */
189751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    pthread_mutex_t vsync_lock;
190751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    int vsync_enabled;
191751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    uint64_t last_vsync_time;
192751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    int last_vsync_time_valid;
193751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    uint64_t fake_vsync_period;
194c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev};
195c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevtypedef struct omap4_hwc_device omap4_hwc_device_t;
196c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
197734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar#define HAL_FMT(f) ((f) == HAL_PIXEL_FORMAT_TI_NV12 ? "NV12" : \
198734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar                    (f) == HAL_PIXEL_FORMAT_YV12 ? "YV12" : \
199734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar                    (f) == HAL_PIXEL_FORMAT_BGRX_8888 ? "xRGB32" : \
200734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar                    (f) == HAL_PIXEL_FORMAT_RGBX_8888 ? "xBGR32" : \
201734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar                    (f) == HAL_PIXEL_FORMAT_BGRA_8888 ? "ARGB32" : \
202734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar                    (f) == HAL_PIXEL_FORMAT_RGBA_8888 ? "ABGR32" : \
203734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar                    (f) == HAL_PIXEL_FORMAT_RGB_565 ? "RGB565" : "??")
204734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar
205734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar#define DSS_FMT(f) ((f) == OMAP_DSS_COLOR_NV12 ? "NV12" : \
206734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar                    (f) == OMAP_DSS_COLOR_RGB24U ? "xRGB32" : \
207734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar                    (f) == OMAP_DSS_COLOR_ARGB32 ? "ARGB32" : \
208734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar                    (f) == OMAP_DSS_COLOR_RGB16 ? "RGB565" : "??")
209734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar
210c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic int debug = 0;
211876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chenstatic int debugpost2 = 0;
212876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chenstatic int debugblt = 0;
213876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chenstatic int gshowfps;
214876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chenstatic rgz_t grgz;
215876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chenstatic struct bvsurfgeom gscrngeom;
216c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2176ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFaddenstatic void dump_layer(hwc_layer_1_t const* l)
218c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
2193a7df2c042eb8c7289e24e77dd316f73bd0c456fSteve Block    ALOGD("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}",
220b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar         l->compositionType, l->flags, l->handle, l->transform, l->blending,
221b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar         l->sourceCrop.left,
222b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar         l->sourceCrop.top,
223b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar         l->sourceCrop.right,
224b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar         l->sourceCrop.bottom,
225b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar         l->displayFrame.left,
226b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar         l->displayFrame.top,
227b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar         l->displayFrame.right,
228b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar         l->displayFrame.bottom);
229c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
230c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
231c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic void dump_dsscomp(struct dsscomp_setup_dispc_data *d)
232c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
23378fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    unsigned i;
234c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2353a7df2c042eb8c7289e24e77dd316f73bd0c456fSteve Block    ALOGD("[%08x] set: %c%c%c %d ovls\n",
236c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev         d->sync_id,
237c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev         (d->mode & DSSCOMP_SETUP_MODE_APPLY) ? 'A' : '-',
238c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev         (d->mode & DSSCOMP_SETUP_MODE_DISPLAY) ? 'D' : '-',
239c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev         (d->mode & DSSCOMP_SETUP_MODE_CAPTURE) ? 'C' : '-',
240c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev         d->num_ovls);
241c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
24278fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    for (i = 0; i < d->num_mgrs; i++) {
24300d8485d3d319633f410e52cab1562fe165af1e3Lajos Molnar        struct dss2_mgr_info *mi = &d->mgrs[i];
2443a7df2c042eb8c7289e24e77dd316f73bd0c456fSteve Block        ALOGD(" (dis%d alpha=%d col=%08x ilace=%d)\n",
245b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar             mi->ix,
246b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar             mi->alpha_blending, mi->default_color,
247b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar             mi->interlaced);
24878fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    }
24978fce72baff38f488a0117591d4241d278a48b1bLajos Molnar
250c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    for (i = 0; i < d->num_ovls; i++) {
25100d8485d3d319633f410e52cab1562fe165af1e3Lajos Molnar        struct dss2_ovl_info *oi = &d->ovls[i];
252b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar        struct dss2_ovl_cfg *c = &oi->cfg;
253b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar        if (c->zonly)
2543a7df2c042eb8c7289e24e77dd316f73bd0c456fSteve Block            ALOGD("ovl%d(%s z%d)\n",
255b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar                 c->ix, c->enabled ? "ON" : "off", c->zorder);
256b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar        else
2573a7df2c042eb8c7289e24e77dd316f73bd0c456fSteve Block            ALOGD("ovl%d(%s z%d %s%s *%d%% %d*%d:%d,%d+%d,%d rot%d%s => %d,%d+%d,%d %p/%p|%d)\n",
258b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar                 c->ix, c->enabled ? "ON" : "off", c->zorder, DSS_FMT(c->color_mode),
259b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar                 c->pre_mult_alpha ? " premult" : "",
260b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar                 (c->global_alpha * 100 + 128) / 255,
261b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar                 c->width, c->height, c->crop.x, c->crop.y,
262b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar                 c->crop.w, c->crop.h,
263b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar                 c->rotation, c->mirror ? "+mir" : "",
264b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar                 c->win.x, c->win.y, c->win.w, c->win.h,
265b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar                 (void *) oi->ba, (void *) oi->uv, c->stride);
266c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    }
267c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
268c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
269734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnarstruct dump_buf {
270734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    char *buf;
271734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    int buf_len;
272734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    int len;
273734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar};
274734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar
275734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnarstatic void dump_printf(struct dump_buf *buf, const char *fmt, ...)
276734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar{
277734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    va_list ap;
278734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar
279734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    va_start(ap, fmt);
280734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    buf->len += vsnprintf(buf->buf + buf->len, buf->buf_len - buf->len, fmt, ap);
281734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    va_end(ap);
282734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar}
283734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar
2846ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFaddenstatic void dump_set_info(omap4_hwc_device_t *hwc_dev, hwc_display_contents_1_t* list)
285734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar{
286876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->comp_data.dsscomp_data;
287734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    char logbuf[1024];
288734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    struct dump_buf log = {
289734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        .buf = logbuf,
290734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        .buf_len = sizeof(logbuf),
291734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    };
292734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    unsigned int i;
293734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar
294734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    dump_printf(&log, "set H{");
295734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    for (i = 0; list && i < list->numHwLayers; i++) {
296734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        if (i)
297734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar            dump_printf(&log, " ");
2986ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden        hwc_layer_1_t *layer = &list->hwLayers[i];
299734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
300876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        if (hwc_dev->post2_blit_buffers) {
301876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            if ((i + 1) < hwc_dev->post2_layers)
302876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                dump_printf(&log, "%p:%s,", handle, "DSS");
303876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            else
304876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                dump_printf(&log, "%p:%s,", handle, "BV2D");
305876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        }
306876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        else
307876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            dump_printf(&log, "%p:%s,", handle, layer->compositionType == HWC_OVERLAY ? "DSS" : "SGX");
308734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        if ((layer->flags & HWC_SKIP_LAYER) || !handle) {
309734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar            dump_printf(&log, "SKIP");
310734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar            continue;
311734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        }
312734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        if (layer->flags & HWC_HINT_CLEAR_FB)
313734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar            dump_printf(&log, "CLR,");
314734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        dump_printf(&log, "%d*%d(%s)", handle->iWidth, handle->iHeight, HAL_FMT(handle->iFormat));
315734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        if (layer->transform)
316734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar            dump_printf(&log, "~%d", layer->transform);
317734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    }
318734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    dump_printf(&log, "} D{");
319734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    for (i = 0; i < dsscomp->num_ovls; i++) {
320734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        if (i)
321734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar            dump_printf(&log, " ");
322734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        dump_printf(&log, "%d=", dsscomp->ovls[i].cfg.ix);
323734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        if (dsscomp->ovls[i].cfg.enabled)
324734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar            dump_printf(&log, "%08x:%d*%d,%s",
325734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar                        dsscomp->ovls[i].ba,
326734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar                        dsscomp->ovls[i].cfg.width,
327734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar                        dsscomp->ovls[i].cfg.height,
328734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar                        DSS_FMT(dsscomp->ovls[i].cfg.color_mode));
329734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        else
330734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar            dump_printf(&log, "-");
331734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    }
332734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    dump_printf(&log, "} L{");
333734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    for (i = 0; i < hwc_dev->post2_layers; i++) {
334734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        if (i)
335734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar            dump_printf(&log, " ");
336734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        dump_printf(&log, "%p", hwc_dev->buffers[i]);
337734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    }
338876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (hwc_dev->post2_blit_buffers) {
339876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        dump_printf(&log, "} B{");
340876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        for (i = hwc_dev->post2_layers;
341876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen             i < hwc_dev->post2_blit_buffers + hwc_dev->post2_layers; i++) {
342876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            dump_printf(&log, "%p ", hwc_dev->buffers[i]);
343876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        }
344876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    }
345734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    dump_printf(&log, "}%s\n", hwc_dev->use_sgx ? " swap" : "");
346734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar
3473a7df2c042eb8c7289e24e77dd316f73bd0c456fSteve Block    ALOGD("%s", log.buf);
348734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar}
349734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar
3505706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnarstatic int sync_id = 0;
3515706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar
352c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic int omap4_hwc_is_valid_format(int format)
353c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
354c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    switch(format) {
355c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    case HAL_PIXEL_FORMAT_RGB_565:
356c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    case HAL_PIXEL_FORMAT_RGBX_8888:
357c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    case HAL_PIXEL_FORMAT_RGBA_8888:
358c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    case HAL_PIXEL_FORMAT_BGRA_8888:
359c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    case HAL_PIXEL_FORMAT_BGRX_8888:
360c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    case HAL_PIXEL_FORMAT_TI_NV12:
361c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    case HAL_PIXEL_FORMAT_TI_NV12_PADDED:
362c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        return 1;
363c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
364c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    default:
365c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        return 0;
366c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    }
367c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
368c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
369876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chenstatic int scaled(hwc_layer_1_t *layer)
370c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
3712704d381ccfba0fe96e61cd368507506c3adfacaLajos Molnar    int w = WIDTH(layer->sourceCrop);
3722704d381ccfba0fe96e61cd368507506c3adfacaLajos Molnar    int h = HEIGHT(layer->sourceCrop);
373d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar
374d4599029522592f46eccf9d57add7ebd7d23fdd1Lajos Molnar    if (layer->transform & HWC_TRANSFORM_ROT_90)
375d4599029522592f46eccf9d57add7ebd7d23fdd1Lajos Molnar        swap(w, h);
376d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar
377876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    return WIDTH(layer->displayFrame) != w || HEIGHT(layer->displayFrame) != h;
378c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
379c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
3806ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFaddenstatic int is_protected(hwc_layer_1_t *layer)
3814ce532200f33ca2c77cd66de924c83decaf7fa30Sunita Nadampalli{
3824ce532200f33ca2c77cd66de924c83decaf7fa30Sunita Nadampalli    IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
3834ce532200f33ca2c77cd66de924c83decaf7fa30Sunita Nadampalli
3844ce532200f33ca2c77cd66de924c83decaf7fa30Sunita Nadampalli    return (handle->usage & GRALLOC_USAGE_PROTECTED);
3854ce532200f33ca2c77cd66de924c83decaf7fa30Sunita Nadampalli}
3864ce532200f33ca2c77cd66de924c83decaf7fa30Sunita Nadampalli
3875706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar#define is_BLENDED(layer) ((layer)->blending != HWC_BLENDING_NONE)
3885706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar
389fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrechtstatic int is_RGB32(IMG_native_handle_t *handle)
390fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht{
391fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht    switch(handle->iFormat)
392fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht    {
393fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht    case HAL_PIXEL_FORMAT_BGRA_8888:
394fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht    case HAL_PIXEL_FORMAT_BGRX_8888:
395fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht        return 1;
396fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht    default:
397fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht        return 0;
398fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht    }
399fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht}
400fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht
4015706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnarstatic int is_RGB(IMG_native_handle_t *handle)
4025706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar{
4035706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    switch(handle->iFormat)
4045706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    {
4055706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    case HAL_PIXEL_FORMAT_BGRA_8888:
4065706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    case HAL_PIXEL_FORMAT_BGRX_8888:
4075706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    case HAL_PIXEL_FORMAT_RGB_565:
4085706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar        return 1;
4095706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    default:
4105706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar        return 0;
4115706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    }
4125706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar}
413c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
4145706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnarstatic int is_BGR_format(int format)
4155706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar{
4165706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    switch (format) {
4175706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    case HAL_PIXEL_FORMAT_RGBX_8888:
4185706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    case HAL_PIXEL_FORMAT_RGBA_8888:
4195706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar        return 1;
4205706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    default:
4215706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar        return 0;
4225706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    }
4235706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar}
424a3a76c576a0a1706c102570697b4fc0017eb46fbMathias Agopian
4255706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnarstatic int is_BGR(IMG_native_handle_t *handle)
4265706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar{
4275706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    return is_BGR_format(handle->iFormat);
4285706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar}
4295706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar
4305706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnarstatic int is_NV12(IMG_native_handle_t *handle)
4315706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar{
4325706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    switch(handle->iFormat)
4335706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    {
4345706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    case HAL_PIXEL_FORMAT_TI_NV12:
4355706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    case HAL_PIXEL_FORMAT_TI_NV12_PADDED:
4365706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar        return 1;
4375706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    default:
4385706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar        return 0;
4395706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    }
4405706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar}
441c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
4426ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFaddenstatic int dockable(hwc_layer_1_t *layer)
443834b8ba01376239a2f286a3766c14bdeeb166498Lajos Molnar{
444834b8ba01376239a2f286a3766c14bdeeb166498Lajos Molnar    IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
445834b8ba01376239a2f286a3766c14bdeeb166498Lajos Molnar
446834b8ba01376239a2f286a3766c14bdeeb166498Lajos Molnar    return (handle->usage & GRALLOC_USAGE_EXTERNAL_DISP);
447834b8ba01376239a2f286a3766c14bdeeb166498Lajos Molnar}
448834b8ba01376239a2f286a3766c14bdeeb166498Lajos Molnar
449751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chenstatic uint64_t vsync_clock_now()
450751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen{
451751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    uint64_t now = 0;
452751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    struct timespec ts;
453751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
454751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    if (!clock_gettime(CLOCK_MONOTONIC, &ts))
455751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        now = ((uint64_t)ts.tv_sec) * 1000000000ull + ts.tv_nsec;
456751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
457751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    return now;
458751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen}
459751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
460751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chenstatic void wakeup_hdmi_thread(omap4_hwc_device_t *hwc_dev)
461751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen{
462751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    uint64_t tmp = 1;
463751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    write(hwc_dev->wakeup_evt, &tmp, sizeof(tmp));
464751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen}
465751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
466751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chenstatic void fire_vsync_event(omap4_hwc_device_t *hwc_dev, uint64_t timestamp)
467751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen{
468751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    pthread_mutex_lock(&hwc_dev->vsync_lock);
469751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
470751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    hwc_dev->last_vsync_time_valid = 1;
471751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    hwc_dev->last_vsync_time = timestamp;
472751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
473751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    pthread_mutex_unlock(&hwc_dev->vsync_lock);
474751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
475876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (hwc_dev->procs && hwc_dev->procs->vsync)
476751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        hwc_dev->procs->vsync(hwc_dev->procs, 0, timestamp);
477751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen}
478751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
47938934f125a600817dded7aeba9639c6a75afe358Lajos Molnarstatic unsigned int mem1d(IMG_native_handle_t *handle)
48038934f125a600817dded7aeba9639c6a75afe358Lajos Molnar{
4815706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    if (handle == NULL || is_NV12(handle))
482b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar        return 0;
48338934f125a600817dded7aeba9639c6a75afe358Lajos Molnar
4845706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    int bpp = handle->iFormat == HAL_PIXEL_FORMAT_RGB_565 ? 2 : 4;
48538934f125a600817dded7aeba9639c6a75afe358Lajos Molnar    int stride = ALIGN(handle->iWidth, HW_ALIGN) * bpp;
48638934f125a600817dded7aeba9639c6a75afe358Lajos Molnar    return stride * handle->iHeight;
48738934f125a600817dded7aeba9639c6a75afe358Lajos Molnar}
48838934f125a600817dded7aeba9639c6a75afe358Lajos Molnar
489c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic void
4905706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnaromap4_hwc_setup_layer_base(struct dss2_ovl_cfg *oc, int index, int format, int blended, int width, int height)
491c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
492c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    unsigned int bits_per_pixel;
493c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
494c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    /* YUV2RGB conversion */
495c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    const struct omap_dss_cconv_coefs ctbl_bt601_5 = {
496c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        298,  409,    0,  298, -208, -100,  298,    0,  517, 0,
497c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    };
498c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
499c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    /* convert color format */
500c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    switch (format) {
501c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    case HAL_PIXEL_FORMAT_RGBA_8888:
502c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    case HAL_PIXEL_FORMAT_BGRA_8888:
503c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        oc->color_mode = OMAP_DSS_COLOR_ARGB32;
504c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        bits_per_pixel = 32;
5055706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar        if (blended)
5065706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar                break;
507c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
5085706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    case HAL_PIXEL_FORMAT_RGBX_8888:
509c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    case HAL_PIXEL_FORMAT_BGRX_8888:
510c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        oc->color_mode = OMAP_DSS_COLOR_RGB24U;
511c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        bits_per_pixel = 32;
512c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        break;
513c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
514c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    case HAL_PIXEL_FORMAT_RGB_565:
515c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        oc->color_mode = OMAP_DSS_COLOR_RGB16;
516c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        bits_per_pixel = 16;
517c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        break;
518c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
519c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    case HAL_PIXEL_FORMAT_TI_NV12:
520c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    case HAL_PIXEL_FORMAT_TI_NV12_PADDED:
521c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        oc->color_mode = OMAP_DSS_COLOR_NV12;
522c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        bits_per_pixel = 8;
523c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        oc->cconv = ctbl_bt601_5;
524c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        break;
525c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
526c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    default:
527c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        /* Should have been filtered out */
528ac837f2654f5a7a7fbecf05e4b085b87a7701714Steve Block        ALOGV("Unsupported pixel format");
529c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        return;
530c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    }
531c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
532c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    oc->width = width;
533c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    oc->height = height;
534c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    oc->stride = ALIGN(width, HW_ALIGN) * bits_per_pixel / 8;
535c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
536c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    oc->enabled = 1;
537c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    oc->global_alpha = 255;
538c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    oc->zorder = index;
539c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    oc->ix = 0;
540c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
541c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    /* defaults for SGX framebuffer renders */
542c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    oc->crop.w = oc->win.w = width;
543c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    oc->crop.h = oc->win.h = height;
544c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
545c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    /* for now interlacing and vc1 info is not supplied */
546c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    oc->ilace = OMAP_DSS_ILACE_NONE;
547c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    oc->vc1.enable = 0;
548c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
549c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
550c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic void
551c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevomap4_hwc_setup_layer(omap4_hwc_device_t *hwc_dev, struct dss2_ovl_info *ovl,
5526ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden                      hwc_layer_1_t *layer, int index,
553c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                      int format, int width, int height)
554c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
555c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    struct dss2_ovl_cfg *oc = &ovl->cfg;
556c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
557c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    //dump_layer(layer);
558c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
5595706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    omap4_hwc_setup_layer_base(oc, index, format, is_BLENDED(layer), width, height);
560c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
561c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    /* convert transformation - assuming 0-set config */
562c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if (layer->transform & HWC_TRANSFORM_FLIP_H)
563c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        oc->mirror = 1;
564c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if (layer->transform & HWC_TRANSFORM_FLIP_V) {
565c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        oc->rotation = 2;
56678fce72baff38f488a0117591d4241d278a48b1bLajos Molnar        oc->mirror = !oc->mirror;
567c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    }
568c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if (layer->transform & HWC_TRANSFORM_ROT_90) {
569c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        oc->rotation += oc->mirror ? -1 : 1;
570c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        oc->rotation &= 3;
571c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    }
572c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
573c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    oc->pre_mult_alpha = layer->blending == HWC_BLENDING_PREMULT;
574c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
575c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    /* display position */
576c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    oc->win.x = layer->displayFrame.left;
577c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    oc->win.y = layer->displayFrame.top;
5782704d381ccfba0fe96e61cd368507506c3adfacaLajos Molnar    oc->win.w = WIDTH(layer->displayFrame);
5792704d381ccfba0fe96e61cd368507506c3adfacaLajos Molnar    oc->win.h = HEIGHT(layer->displayFrame);
580c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
581c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    /* crop */
582c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    oc->crop.x = layer->sourceCrop.left;
583c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    oc->crop.y = layer->sourceCrop.top;
5842704d381ccfba0fe96e61cd368507506c3adfacaLajos Molnar    oc->crop.w = WIDTH(layer->sourceCrop);
5852704d381ccfba0fe96e61cd368507506c3adfacaLajos Molnar    oc->crop.h = HEIGHT(layer->sourceCrop);
586c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
587c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
5882952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnarconst float m_unit[2][3] = { { 1., 0., 0. }, { 0., 1., 0. } };
5892952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar
5902952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnarstatic inline void m_translate(float m[2][3], int dx, int dy)
5912952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar{
5922952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar    m[0][2] += dx;
5932952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar    m[1][2] += dy;
5942952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar}
5952952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar
5962952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnarstatic inline void m_scale1(float m[3], int from, int to)
5972952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar{
5982952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar    m[0] = m[0] * to / from;
5992952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar    m[1] = m[1] * to / from;
6002952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar    m[2] = m[2] * to / from;
6012952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar}
6022952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar
6032952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnarstatic inline void m_scale(float m[2][3], int x_from, int x_to, int y_from, int y_to)
6042952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar{
6052952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar    m_scale1(m[0], x_from, x_to);
6062952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar    m_scale1(m[1], y_from, y_to);
6072952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar}
6082952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar
6092952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnarstatic void m_rotate(float m[2][3], int quarter_turns)
6102952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar{
6112952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar    if (quarter_turns & 2)
6122952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar        m_scale(m, 1, -1, 1, -1);
6132952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar    if (quarter_turns & 1) {
6142952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar        int q;
6152952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar        q = m[0][0]; m[0][0] = -m[1][0]; m[1][0] = q;
6162952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar        q = m[0][1]; m[0][1] = -m[1][1]; m[1][1] = q;
6172952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar        q = m[0][2]; m[0][2] = -m[1][2]; m[1][2] = q;
6182952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar    }
6192952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar}
6202952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar
6212952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnarstatic inline int m_round(float x)
6222952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar{
6232952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar    /* int truncates towards 0 */
6242952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar    return (int) (x < 0 ? x - 0.5 : x + 0.5);
6252952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar}
6262952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar
627ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar/*
6281b24d08333d1f847e6211aaa1b81f5792aca2704Lajos Molnar * assuming xpy (xratio:yratio) original pixel ratio, calculate the adjusted width
629ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar * and height for a screen of xres/yres and physical size of width/height.
630ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar * The adjusted size is the largest that fits into the screen.
631ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar */
632ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnarstatic void get_max_dimensions(__u32 orig_xres, __u32 orig_yres,
6331b24d08333d1f847e6211aaa1b81f5792aca2704Lajos Molnar                               float xpy,
634ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar                               __u32 scr_xres, __u32 scr_yres,
635ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar                               __u32 scr_width, __u32 scr_height,
636ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar                               __u32 *adj_xres, __u32 *adj_yres)
637ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar{
638ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar    /* assume full screen (largest size)*/
639ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar    *adj_xres = scr_xres;
640ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar    *adj_yres = scr_yres;
641ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar
642ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar    /* assume 1:1 pixel ratios if none supplied */
643ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar    if (!scr_width || !scr_height) {
644ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar        scr_width = scr_xres;
645ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar        scr_height = scr_yres;
646ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar    }
647ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar
648ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar    /* trim to keep aspect ratio */
6491b24d08333d1f847e6211aaa1b81f5792aca2704Lajos Molnar    float x_factor = orig_xres * xpy * scr_height;
6501b24d08333d1f847e6211aaa1b81f5792aca2704Lajos Molnar    float y_factor = orig_yres *       scr_width;
651ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar
652ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar    /* allow for tolerance so we avoid scaling if framebuffer is standard size */
653ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar    if (x_factor < y_factor * (1.f - ASPECT_RATIO_TOLERANCE))
654ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar        *adj_xres = (__u32) (x_factor * *adj_xres / y_factor + 0.5);
655ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar    else if (x_factor * (1.f - ASPECT_RATIO_TOLERANCE) > y_factor)
656ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar        *adj_yres = (__u32) (y_factor * *adj_yres / x_factor + 0.5);
657ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar}
658ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar
6598d546610cba3698c62af537d97e38a7368362f1aLajos Molnarstatic void set_ext_matrix(omap4_hwc_ext_t *ext, struct hwc_rect region)
6602952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar{
6618d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    int orig_w = WIDTH(region);
6628d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    int orig_h = HEIGHT(region);
6633797fa989f5fee97caea2bbadf433a5a9ac03d8dLajos Molnar    float xpy = ext->lcd_xpy;
6642952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar
6652952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar    /* reorientation matrix is:
6662952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar       m = (center-from-target-center) * (scale-to-target) * (mirror) * (rotate) * (center-to-original-center) */
6672952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar
668ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    memcpy(ext->m, m_unit, sizeof(m_unit));
6698d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    m_translate(ext->m, -(orig_w >> 1) - region.left, -(orig_h >> 1) - region.top);
670ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    m_rotate(ext->m, ext->current.rotation);
671ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    if (ext->current.hflip)
672ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar        m_scale(ext->m, 1, -1, 1, 1);
6732952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar
674ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    if (ext->current.rotation & 1) {
675d4599029522592f46eccf9d57add7ebd7d23fdd1Lajos Molnar        swap(orig_w, orig_h);
6761b24d08333d1f847e6211aaa1b81f5792aca2704Lajos Molnar        xpy = 1. / xpy;
6772952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar    }
6782952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar
679ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar    /* get target size */
680ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar    __u32 adj_xres, adj_yres;
6811b24d08333d1f847e6211aaa1b81f5792aca2704Lajos Molnar    get_max_dimensions(orig_w, orig_h, xpy,
682ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar                       ext->xres, ext->yres, ext->width, ext->height,
683ae5ccc208800debb41acfc45096d318847e8db50Lajos Molnar                       &adj_xres, &adj_yres);
6842952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar
685ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    m_scale(ext->m, orig_w, adj_xres, orig_h, adj_yres);
686ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    m_translate(ext->m, ext->xres >> 1, ext->yres >> 1);
6872952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar}
6882952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar
6898d546610cba3698c62af537d97e38a7368362f1aLajos Molnarstatic int
6908d546610cba3698c62af537d97e38a7368362f1aLajos Molnarcrop_to_rect(struct dss2_ovl_cfg *cfg, struct hwc_rect vis_rect)
6918d546610cba3698c62af537d97e38a7368362f1aLajos Molnar{
6928d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    struct {
6938d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        int xy[2];
6948d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        int wh[2];
6958d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    } crop, win;
6968d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    struct {
6978d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        int lt[2];
6988d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        int rb[2];
6998d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    } vis;
7008d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    win.xy[0] = cfg->win.x; win.xy[1] = cfg->win.y;
7018d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    win.wh[0] = cfg->win.w; win.wh[1] = cfg->win.h;
7028d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    crop.xy[0] = cfg->crop.x; crop.xy[1] = cfg->crop.y;
7038d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    crop.wh[0] = cfg->crop.w; crop.wh[1] = cfg->crop.h;
7048d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    vis.lt[0] = vis_rect.left; vis.lt[1] = vis_rect.top;
7058d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    vis.rb[0] = vis_rect.right; vis.rb[1] = vis_rect.bottom;
7068d546610cba3698c62af537d97e38a7368362f1aLajos Molnar
7078d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    int c, swap = cfg->rotation & 1;
7088d546610cba3698c62af537d97e38a7368362f1aLajos Molnar
7098d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    /* align crop window with display coordinates */
7108d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    if (swap)
7118d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        crop.xy[1] -= (crop.wh[1] = -crop.wh[1]);
7128d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    if (cfg->rotation & 2)
7138d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        crop.xy[!swap] -= (crop.wh[!swap] = -crop.wh[!swap]);
7148d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    if ((!cfg->mirror) ^ !(cfg->rotation & 2))
7158d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        crop.xy[swap] -= (crop.wh[swap] = -crop.wh[swap]);
7168d546610cba3698c62af537d97e38a7368362f1aLajos Molnar
7178d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    for (c = 0; c < 2; c++) {
7188d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        /* see if complete buffer is outside the vis or it is
7198d546610cba3698c62af537d97e38a7368362f1aLajos Molnar          fully cropped or scaled to 0 */
7208d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        if (win.wh[c] <= 0 || vis.rb[c] <= vis.lt[c] ||
7218d546610cba3698c62af537d97e38a7368362f1aLajos Molnar            win.xy[c] + win.wh[c] <= vis.lt[c] ||
7228d546610cba3698c62af537d97e38a7368362f1aLajos Molnar            win.xy[c] >= vis.rb[c] ||
7238d546610cba3698c62af537d97e38a7368362f1aLajos Molnar            !crop.wh[c ^ swap])
7248d546610cba3698c62af537d97e38a7368362f1aLajos Molnar            return -ENOENT;
7258d546610cba3698c62af537d97e38a7368362f1aLajos Molnar
7268d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        /* crop left/top */
7278d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        if (win.xy[c] < vis.lt[c]) {
7288d546610cba3698c62af537d97e38a7368362f1aLajos Molnar            /* correction term */
7298d546610cba3698c62af537d97e38a7368362f1aLajos Molnar            int a = (vis.lt[c] - win.xy[c]) * crop.wh[c ^ swap] / win.wh[c];
7308d546610cba3698c62af537d97e38a7368362f1aLajos Molnar            crop.xy[c ^ swap] += a;
7318d546610cba3698c62af537d97e38a7368362f1aLajos Molnar            crop.wh[c ^ swap] -= a;
7328d546610cba3698c62af537d97e38a7368362f1aLajos Molnar            win.wh[c] -= vis.lt[c] - win.xy[c];
7338d546610cba3698c62af537d97e38a7368362f1aLajos Molnar            win.xy[c] = vis.lt[c];
7348d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        }
7358d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        /* crop right/bottom */
7368d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        if (win.xy[c] + win.wh[c] > vis.rb[c]) {
7378d546610cba3698c62af537d97e38a7368362f1aLajos Molnar            crop.wh[c ^ swap] = crop.wh[c ^ swap] * (vis.rb[c] - win.xy[c]) / win.wh[c];
7388d546610cba3698c62af537d97e38a7368362f1aLajos Molnar            win.wh[c] = vis.rb[c] - win.xy[c];
7398d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        }
7408d546610cba3698c62af537d97e38a7368362f1aLajos Molnar
7418d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        if (!crop.wh[c ^ swap] || !win.wh[c])
7428d546610cba3698c62af537d97e38a7368362f1aLajos Molnar            return -ENOENT;
7438d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    }
7448d546610cba3698c62af537d97e38a7368362f1aLajos Molnar
7458d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    /* realign crop window to buffer coordinates */
7468d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    if (cfg->rotation & 2)
7478d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        crop.xy[!swap] -= (crop.wh[!swap] = -crop.wh[!swap]);
7488d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    if ((!cfg->mirror) ^ !(cfg->rotation & 2))
7498d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        crop.xy[swap] -= (crop.wh[swap] = -crop.wh[swap]);
7508d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    if (swap)
7518d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        crop.xy[1] -= (crop.wh[1] = -crop.wh[1]);
7528d546610cba3698c62af537d97e38a7368362f1aLajos Molnar
7538d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    cfg->win.x = win.xy[0]; cfg->win.y = win.xy[1];
7548d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    cfg->win.w = win.wh[0]; cfg->win.h = win.wh[1];
7558d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    cfg->crop.x = crop.xy[0]; cfg->crop.y = crop.xy[1];
7568d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    cfg->crop.w = crop.wh[0]; cfg->crop.h = crop.wh[1];
7578d546610cba3698c62af537d97e38a7368362f1aLajos Molnar
7588d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    return 0;
7598d546610cba3698c62af537d97e38a7368362f1aLajos Molnar}
7608d546610cba3698c62af537d97e38a7368362f1aLajos Molnar
7612952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnarstatic void
762876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chenomap4_hwc_apply_transform(float transform[2][3],struct dss2_ovl_cfg *oc)
7632952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar{
7642952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar    float x, y, w, h;
7652952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar
7662952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar    /* display position */
767876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    x = transform[0][0] * oc->win.x + transform[0][1] * oc->win.y + transform[0][2];
768876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    y = transform[1][0] * oc->win.x + transform[1][1] * oc->win.y + transform[1][2];
769876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    w = transform[0][0] * oc->win.w + transform[0][1] * oc->win.h;
770876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    h = transform[1][0] * oc->win.w + transform[1][1] * oc->win.h;
7712952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar    oc->win.x = m_round(w > 0 ? x : x + w);
7722952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar    oc->win.y = m_round(h > 0 ? y : y + h);
7732952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar    oc->win.w = m_round(w > 0 ? w : -w);
7742952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar    oc->win.h = m_round(h > 0 ? h : -h);
7752952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar}
7762952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar
7775db21d521ed41e2e2cc110b698981e841e027287Dandawate Saketstatic void
778876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chenomap4_hwc_adjust_ext_layer(omap4_hwc_ext_t *ext, struct dss2_ovl_info *ovl)
7795db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket{
7805db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket    struct dss2_ovl_cfg *oc = &ovl->cfg;
7815db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket
782876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    /* crop to clone region if mirroring */
783876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (!ext->current.docking &&
784876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        crop_to_rect(&ovl->cfg, ext->mirror_region) != 0) {
7855db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket        ovl->cfg.enabled = 0;
7865db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket        return;
7875db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket    }
7885db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket
789876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    omap4_hwc_apply_transform(ext->m, oc);
7905db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket
7915db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket    /* combining transformations: F^a*R^b*F^i*R^j = F^(a+b)*R^(j+b*(-1)^i), because F*R = R^(-1)*F */
792876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    oc->rotation += (oc->mirror ? -1 : 1) * ext->current.rotation;
7935db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket    oc->rotation &= 3;
794876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (ext->current.hflip)
795876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        oc->mirror = !oc->mirror;
7965db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket}
797876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
798876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chenstatic struct dsscomp_platform_info limits;
799876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
8005db21d521ed41e2e2cc110b698981e841e027287Dandawate Saketstatic void
801876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chenomap4_hwc_adjust_primary_display_layer(omap4_hwc_device_t *hwc_dev, struct dss2_ovl_info *ovl)
8025db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket{
8035db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket    struct dss2_ovl_cfg *oc = &ovl->cfg;
8045db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket
805876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (crop_to_rect(&ovl->cfg, hwc_dev->primary_region) != 0) {
8065db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket        ovl->cfg.enabled = 0;
8075db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket        return;
8085db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket    }
8095db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket
810876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    omap4_hwc_apply_transform(hwc_dev->primary_m, oc);
8115db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket
812876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    /* combining transformations: F^a*R^b*F^i*R^j = F^(a+b)*R^(j+b*(-1)^i), because F*R = R^(-1)*F */
813876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    oc->rotation += (oc->mirror ? -1 : 1) * hwc_dev->primary_rotation;
814876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    oc->rotation &= 3;
8155db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket}
8165db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket
817e055e4bf77e6c429d7a159e8e853974d9dfc57adLajos Molnarstatic int omap4_hwc_can_scale(__u32 src_w, __u32 src_h, __u32 dst_w, __u32 dst_h, int is_2d,
818876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                               struct dsscomp_display_info *dis, struct dsscomp_platform_info *limits,
8194ceb627d195b2efb8cfa3612f38cee211436a7a2Lajos Molnar                               __u32 pclk)
820d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar{
821d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar    __u32 fclk = limits->fclk / 1000;
82216b7f6c4b06ac7350c30309d0559a466097d8ae7Lajos Molnar    __u32 min_src_w = DIV_ROUND_UP(src_w, is_2d ? limits->max_xdecim_2d : limits->max_xdecim_1d);
82316b7f6c4b06ac7350c30309d0559a466097d8ae7Lajos Molnar    __u32 min_src_h = DIV_ROUND_UP(src_h, is_2d ? limits->max_ydecim_2d : limits->max_ydecim_1d);
824d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar
825d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar    /* ERRATAs */
826d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar    /* cannot render 1-width layers on DSI video mode panels - we just disallow all 1-width LCD layers */
827d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar    if (dis->channel != OMAP_DSS_CHANNEL_DIGIT && dst_w < limits->min_width)
828d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar        return 0;
829d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar
830d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar    /* NOTE: no support for checking YUV422 layers that are tricky to scale */
831d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar
8321a45d7e2f85f1e3f3eeef590aa52316376055440Mathias Agopian    /* FIXME: limit vertical downscale well below theoretical limit as we saw display artifacts */
8331a45d7e2f85f1e3f3eeef590aa52316376055440Mathias Agopian    if (dst_h < src_h / 4)
8341a45d7e2f85f1e3f3eeef590aa52316376055440Mathias Agopian        return 0;
8351a45d7e2f85f1e3f3eeef590aa52316376055440Mathias Agopian
836d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar    /* max downscale */
83716b7f6c4b06ac7350c30309d0559a466097d8ae7Lajos Molnar    if (dst_h * limits->max_downscale < min_src_h)
838d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar        return 0;
839d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar
8404ceb627d195b2efb8cfa3612f38cee211436a7a2Lajos Molnar    /* for manual panels pclk is 0, and there are no pclk based scaling limits */
8414ceb627d195b2efb8cfa3612f38cee211436a7a2Lajos Molnar    if (!pclk)
84216b7f6c4b06ac7350c30309d0559a466097d8ae7Lajos Molnar        return !(dst_w * limits->max_downscale < min_src_w);
8434ceb627d195b2efb8cfa3612f38cee211436a7a2Lajos Molnar
844d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar    /* :HACK: limit horizontal downscale well below theoretical limit as we saw display artifacts */
84516b7f6c4b06ac7350c30309d0559a466097d8ae7Lajos Molnar    if (dst_w * 4 < src_w)
846d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar        return 0;
847d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar
848d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar    /* max horizontal downscale is 4, or the fclk/pixclk */
849d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar    if (fclk > pclk * limits->max_downscale)
850d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar        fclk = pclk * limits->max_downscale;
851d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar    /* for small parts, we need to use integer fclk/pixclk */
852d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar    if (src_w < limits->integer_scale_ratio_limit)
853d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar        fclk = fclk / pclk * pclk;
85416b7f6c4b06ac7350c30309d0559a466097d8ae7Lajos Molnar    if ((__u32) dst_w * fclk < min_src_w * pclk)
855d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar        return 0;
856d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar
857d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar    return 1;
858d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar}
859d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar
8606ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFaddenstatic int omap4_hwc_can_scale_layer(omap4_hwc_device_t *hwc_dev, hwc_layer_1_t *layer, IMG_native_handle_t *handle)
861d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar{
8622704d381ccfba0fe96e61cd368507506c3adfacaLajos Molnar    int src_w = WIDTH(layer->sourceCrop);
8632704d381ccfba0fe96e61cd368507506c3adfacaLajos Molnar    int src_h = HEIGHT(layer->sourceCrop);
8642704d381ccfba0fe96e61cd368507506c3adfacaLajos Molnar    int dst_w = WIDTH(layer->displayFrame);
8652704d381ccfba0fe96e61cd368507506c3adfacaLajos Molnar    int dst_h = HEIGHT(layer->displayFrame);
866d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar
867d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar    /* account for 90-degree rotation */
868d4599029522592f46eccf9d57add7ebd7d23fdd1Lajos Molnar    if (layer->transform & HWC_TRANSFORM_ROT_90)
869d4599029522592f46eccf9d57add7ebd7d23fdd1Lajos Molnar        swap(src_w, src_h);
870d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar
8714ceb627d195b2efb8cfa3612f38cee211436a7a2Lajos Molnar    /* NOTE: layers should be able to be scaled externally since
8724ceb627d195b2efb8cfa3612f38cee211436a7a2Lajos Molnar       framebuffer is able to be scaled on selected external resolution */
8735706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    return omap4_hwc_can_scale(src_w, src_h, dst_w, dst_h, is_NV12(handle), &hwc_dev->fb_dis, &limits,
8744ceb627d195b2efb8cfa3612f38cee211436a7a2Lajos Molnar                               hwc_dev->fb_dis.timings.pixel_clock);
875d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar}
876d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar
877d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnarstatic int omap4_hwc_is_valid_layer(omap4_hwc_device_t *hwc_dev,
8786ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden                                    hwc_layer_1_t *layer,
879c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                                    IMG_native_handle_t *handle)
880c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
881c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    /* Skip layers are handled by SF */
882c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ((layer->flags & HWC_SKIP_LAYER) || !handle)
883c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        return 0;
884c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
885c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if (!omap4_hwc_is_valid_format(handle->iFormat))
886c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        return 0;
887c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
888c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    /* 1D buffers: no transform, must fit in TILER slot */
8895706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar    if (!is_NV12(handle)) {
890c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        if (layer->transform)
891c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            return 0;
892876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        if (mem1d(handle) > limits.tiler1d_slot_size)
893c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            return 0;
894c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    }
895d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar
896d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar    return omap4_hwc_can_scale_layer(hwc_dev, layer, handle);
897c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
898c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
899e14d52936107e390e2464df1e6653efde5409096Lajos Molnarstatic __u32 add_scaling_score(__u32 score,
900e14d52936107e390e2464df1e6653efde5409096Lajos Molnar                               __u32 xres, __u32 yres, __u32 refresh,
901e14d52936107e390e2464df1e6653efde5409096Lajos Molnar                               __u32 ext_xres, __u32 ext_yres,
902e14d52936107e390e2464df1e6653efde5409096Lajos Molnar                               __u32 mode_xres, __u32 mode_yres, __u32 mode_refresh)
903e14d52936107e390e2464df1e6653efde5409096Lajos Molnar{
904e14d52936107e390e2464df1e6653efde5409096Lajos Molnar    __u32 area = xres * yres;
905e14d52936107e390e2464df1e6653efde5409096Lajos Molnar    __u32 ext_area = ext_xres * ext_yres;
906e14d52936107e390e2464df1e6653efde5409096Lajos Molnar    __u32 mode_area = mode_xres * mode_yres;
907e14d52936107e390e2464df1e6653efde5409096Lajos Molnar
908e14d52936107e390e2464df1e6653efde5409096Lajos Molnar    /* prefer to upscale (1% tolerance) [0..1] (insert after 1st bit) */
909e14d52936107e390e2464df1e6653efde5409096Lajos Molnar    int upscale = (ext_xres >= xres * 99 / 100 && ext_yres >= yres * 99 / 100);
910e14d52936107e390e2464df1e6653efde5409096Lajos Molnar    score = (((score & ~1) | upscale) << 1) | (score & 1);
911e14d52936107e390e2464df1e6653efde5409096Lajos Molnar
912e14d52936107e390e2464df1e6653efde5409096Lajos Molnar    /* pick minimum scaling [0..16] */
913e14d52936107e390e2464df1e6653efde5409096Lajos Molnar    if (ext_area > area)
914e14d52936107e390e2464df1e6653efde5409096Lajos Molnar        score = (score << 5) | (16 * area / ext_area);
915e14d52936107e390e2464df1e6653efde5409096Lajos Molnar    else
916e14d52936107e390e2464df1e6653efde5409096Lajos Molnar        score = (score << 5) | (16 * ext_area / area);
917e14d52936107e390e2464df1e6653efde5409096Lajos Molnar
918e14d52936107e390e2464df1e6653efde5409096Lajos Molnar    /* pick smallest leftover area [0..16] */
919e14d52936107e390e2464df1e6653efde5409096Lajos Molnar    score = (score << 5) | ((16 * ext_area + (mode_area >> 1)) / mode_area);
920e14d52936107e390e2464df1e6653efde5409096Lajos Molnar
921e14d52936107e390e2464df1e6653efde5409096Lajos Molnar    /* adjust mode refresh rate */
922e14d52936107e390e2464df1e6653efde5409096Lajos Molnar    mode_refresh += mode_refresh % 6 == 5;
923e14d52936107e390e2464df1e6653efde5409096Lajos Molnar
924e14d52936107e390e2464df1e6653efde5409096Lajos Molnar    /* prefer same or higher frame rate */
925e14d52936107e390e2464df1e6653efde5409096Lajos Molnar    upscale = (mode_refresh >= refresh);
926e14d52936107e390e2464df1e6653efde5409096Lajos Molnar    score = (score << 1) | upscale;
927e14d52936107e390e2464df1e6653efde5409096Lajos Molnar
928e14d52936107e390e2464df1e6653efde5409096Lajos Molnar    /* pick closest frame rate */
929e14d52936107e390e2464df1e6653efde5409096Lajos Molnar    if (mode_refresh > refresh)
930e14d52936107e390e2464df1e6653efde5409096Lajos Molnar        score = (score << 8) | (240 * refresh / mode_refresh);
931e14d52936107e390e2464df1e6653efde5409096Lajos Molnar    else
932e14d52936107e390e2464df1e6653efde5409096Lajos Molnar        score = (score << 8) | (240 * mode_refresh / refresh);
933e14d52936107e390e2464df1e6653efde5409096Lajos Molnar
934e14d52936107e390e2464df1e6653efde5409096Lajos Molnar    return score;
935e14d52936107e390e2464df1e6653efde5409096Lajos Molnar}
936e14d52936107e390e2464df1e6653efde5409096Lajos Molnar
93704c7041e0dc1e9c7d2c4e1be1e78a092de993c27Lajos Molnarstatic int omap4_hwc_set_best_hdmi_mode(omap4_hwc_device_t *hwc_dev, __u32 xres, __u32 yres,
9381b24d08333d1f847e6211aaa1b81f5792aca2704Lajos Molnar                                        float xpy)
939bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar{
9405db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket    int dis_ix = hwc_dev->on_tv ? 0 : 1;
941ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen    int forced_preferred_mode = 0;
9425db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket
943bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar    struct _qdis {
944bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar        struct dsscomp_display_info dis;
94504512dd8a3fd2830139e3f352a295841c7eed190Travis Geiselbrecht        struct dsscomp_videomode modedb[32];
9465db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket    } d = { .dis = { .ix = dis_ix } };
947ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    omap4_hwc_ext_t *ext = &hwc_dev->ext;
948bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar
949bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar    d.dis.modedb_len = sizeof(d.modedb) / sizeof(*d.modedb);
950cb64c2be21ad9550b1f5d2b4a8361e997b9be757Lajos Molnar    int ret = ioctl(hwc_dev->dsscomp_fd, DSSCIOC_QUERY_DISPLAY, &d);
951bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar    if (ret)
952bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar        return ret;
953bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar
9546c12df17d9a51d20ca799ca22ffee6818d438c94Lajos Molnar    if (d.dis.timings.x_res * d.dis.timings.y_res == 0 ||
9556c12df17d9a51d20ca799ca22ffee6818d438c94Lajos Molnar        xres * yres == 0)
9566c12df17d9a51d20ca799ca22ffee6818d438c94Lajos Molnar        return -EINVAL;
9576c12df17d9a51d20ca799ca22ffee6818d438c94Lajos Molnar
958bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar    __u32 i, best = ~0, best_score = 0;
959ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    ext->width = d.dis.width_in_mm;
960ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    ext->height = d.dis.height_in_mm;
961ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    ext->xres = d.dis.timings.x_res;
962ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    ext->yres = d.dis.timings.y_res;
9633837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar
9643837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    /* use VGA external resolution as default */
9653837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    if (!ext->xres || !ext->yres) {
9663837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar        ext->xres = 640;
9673837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar        ext->yres = 480;
9683837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    }
9693837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar
970ab9d83c73ae44ed9a8479d17ab4ab6b11354e8c4Travis Geiselbrecht    /*
971ab9d83c73ae44ed9a8479d17ab4ab6b11354e8c4Travis Geiselbrecht     * copy the xres/yres from the preferred mode
972ab9d83c73ae44ed9a8479d17ab4ab6b11354e8c4Travis Geiselbrecht     */
973ab9d83c73ae44ed9a8479d17ab4ab6b11354e8c4Travis Geiselbrecht    __u32 preferred_mode_xres = 0;
974ab9d83c73ae44ed9a8479d17ab4ab6b11354e8c4Travis Geiselbrecht    __u32 preferred_mode_yres = 0;
975ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen
976ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen    char value[PROPERTY_VALUE_MAX];
977ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen    if (property_get("persist.hwc.preferred_mode", value, "") <= 0 ||
978ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen        sscanf(value, "%dx%d", &preferred_mode_xres,
979ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen               &preferred_mode_yres) != 2) {
980ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen        for (i = 0; i < d.dis.modedb_len; i++) {
981ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen            if (d.modedb[i].flag & FB_FLAG_PREFERRED) {
982ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen                preferred_mode_xres = d.modedb[i].xres;
983ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen                preferred_mode_yres = d.modedb[i].yres;
984ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen                ALOGD("preferred mode %d: xres %u yres %u\n",
985ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen                    i, d.modedb[i].xres, d.modedb[i].yres);
986ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen                break;
987ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen            }
988ab9d83c73ae44ed9a8479d17ab4ab6b11354e8c4Travis Geiselbrecht        }
989ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen    } else {
990ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen        ALOGD("forced preferred mode xres %u yres %u\n",
991ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen             preferred_mode_xres, preferred_mode_yres);
992ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen        forced_preferred_mode = 1;
993ab9d83c73ae44ed9a8479d17ab4ab6b11354e8c4Travis Geiselbrecht    }
994ab9d83c73ae44ed9a8479d17ab4ab6b11354e8c4Travis Geiselbrecht
995bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar    __u32 ext_fb_xres, ext_fb_yres;
996bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar    for (i = 0; i < d.dis.modedb_len; i++) {
997bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar        __u32 score = 0;
998e14d52936107e390e2464df1e6653efde5409096Lajos Molnar        __u32 mode_xres = d.modedb[i].xres;
999e14d52936107e390e2464df1e6653efde5409096Lajos Molnar        __u32 mode_yres = d.modedb[i].yres;
1000bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar        __u32 ext_width = d.dis.width_in_mm;
1001bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar        __u32 ext_height = d.dis.height_in_mm;
1002bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar
1003ab9d83c73ae44ed9a8479d17ab4ab6b11354e8c4Travis Geiselbrecht        /* reject it because the hw says it can't actually use this mode */
1004ab9d83c73ae44ed9a8479d17ab4ab6b11354e8c4Travis Geiselbrecht        if ((d.modedb[i].flag & FB_FLAG_HW_CAPABLE) == 0)
1005ab9d83c73ae44ed9a8479d17ab4ab6b11354e8c4Travis Geiselbrecht            continue;
1006ab9d83c73ae44ed9a8479d17ab4ab6b11354e8c4Travis Geiselbrecht
1007bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar        if (d.modedb[i].flag & FB_FLAG_RATIO_4_3) {
1008bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar            ext_width = 4;
1009bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar            ext_height = 3;
1010bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar        } else if (d.modedb[i].flag & FB_FLAG_RATIO_16_9) {
1011bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar            ext_width = 16;
1012bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar            ext_height = 9;
1013bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar        }
1014bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar
1015e14d52936107e390e2464df1e6653efde5409096Lajos Molnar        if (!mode_xres || !mode_yres)
10166c12df17d9a51d20ca799ca22ffee6818d438c94Lajos Molnar            continue;
10176c12df17d9a51d20ca799ca22ffee6818d438c94Lajos Molnar
1018e14d52936107e390e2464df1e6653efde5409096Lajos Molnar        get_max_dimensions(xres, yres, xpy, mode_xres, mode_yres,
1019bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar                           ext_width, ext_height, &ext_fb_xres, &ext_fb_yres);
1020bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar
1021f4524c063d4cc4afeb19b08966f51b42257d3acdLajos Molnar        /* we need to ensure that even TILER2D buffers can be scaled */
10224ceb627d195b2efb8cfa3612f38cee211436a7a2Lajos Molnar        if (!d.modedb[i].pixclock ||
10230f28098bbd8976f5a182604226da293747ac824bLajos Molnar            d.modedb[i].vmode ||
10244ceb627d195b2efb8cfa3612f38cee211436a7a2Lajos Molnar            !omap4_hwc_can_scale(xres, yres, ext_fb_xres, ext_fb_yres,
1025ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar                                 1, &d.dis, &limits,
10264ceb627d195b2efb8cfa3612f38cee211436a7a2Lajos Molnar                                 1000000000 / d.modedb[i].pixclock))
1027bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar            continue;
1028bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar
1029bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar        /* prefer CEA modes */
1030bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar        if (d.modedb[i].flag & (FB_FLAG_RATIO_4_3 | FB_FLAG_RATIO_16_9))
1031ab9d83c73ae44ed9a8479d17ab4ab6b11354e8c4Travis Geiselbrecht            score += 1;
1032ab9d83c73ae44ed9a8479d17ab4ab6b11354e8c4Travis Geiselbrecht
1033ab9d83c73ae44ed9a8479d17ab4ab6b11354e8c4Travis Geiselbrecht        /* prefer modes that match the preferred mode's resolution */
1034ab9d83c73ae44ed9a8479d17ab4ab6b11354e8c4Travis Geiselbrecht        if (d.modedb[i].xres == preferred_mode_xres &&
1035ab9d83c73ae44ed9a8479d17ab4ab6b11354e8c4Travis Geiselbrecht            d.modedb[i].yres == preferred_mode_yres) {
1036ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen            if (forced_preferred_mode)
1037ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen                score += 10;
1038ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen            else
1039ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen                score += 1;
1040ab9d83c73ae44ed9a8479d17ab4ab6b11354e8c4Travis Geiselbrecht        }
1041ab9d83c73ae44ed9a8479d17ab4ab6b11354e8c4Travis Geiselbrecht
1042ab9d83c73ae44ed9a8479d17ab4ab6b11354e8c4Travis Geiselbrecht        /* prefer modes the kernel has hinted is the correct mode */
1043ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen        if (!forced_preferred_mode && (d.modedb[i].flag & FB_FLAG_PREFERRED))
1044ab9d83c73ae44ed9a8479d17ab4ab6b11354e8c4Travis Geiselbrecht            score += 1;
1045bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar
10464e635e537afaa9f1416fa5bdbfd1b03afd8b7e6aLajos Molnar        /* prefer the same mode as we use for mirroring to avoid mode change */
1047ef2e2467d7c5487cf3be888956adcdc686b03412Mike J. Chen        score = (score << 1) | (i == ~ext->mirror_mode && ext->avoid_mode_change);
1048bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar
1049e14d52936107e390e2464df1e6653efde5409096Lajos Molnar        score = add_scaling_score(score, xres, yres, 60, ext_fb_xres, ext_fb_yres,
1050e14d52936107e390e2464df1e6653efde5409096Lajos Molnar                                  mode_xres, mode_yres, d.modedb[i].refresh ? : 1);
1051bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar
1052876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        ALOGD("#%d: %dx%d %dHz flag 0x%x vmode 0x%x, score 0x%x",
1053876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen             i, mode_xres, mode_yres,
1054876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen             d.modedb[i].refresh, d.modedb[i].flag, d.modedb[i].vmode,
1055876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen             score);
1056876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1057bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar        if (debug)
10583a7df2c042eb8c7289e24e77dd316f73bd0c456fSteve Block            ALOGD("  score=0x%x adj.res=%dx%d", score, ext_fb_xres, ext_fb_yres);
1059bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar        if (best_score < score) {
1060ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar            ext->width = ext_width;
1061ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar            ext->height = ext_height;
1062e14d52936107e390e2464df1e6653efde5409096Lajos Molnar            ext->xres = mode_xres;
1063e14d52936107e390e2464df1e6653efde5409096Lajos Molnar            ext->yres = mode_yres;
1064bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar            best = i;
1065bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar            best_score = score;
1066bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar        }
1067bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar    }
1068bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar    if (~best) {
10695db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket        struct dsscomp_setup_display_data sdis = { .ix = dis_ix, };
1070bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar        sdis.mode = d.dis.modedb[best];
10713a7df2c042eb8c7289e24e77dd316f73bd0c456fSteve Block        ALOGD("picking #%d", best);
10724cb51e55fa79a592d50d94c0700660e42c988a0bLajos Molnar        /* only reconfigure on change */
10735142031872205241cfc707a7ac9bd77d095ff0f8Mike J. Chen        if (ext->last_mode != ~best) {
10745142031872205241cfc707a7ac9bd77d095ff0f8Mike J. Chen            /* set a property that apps that care (e.g. YouTube) can use
10755142031872205241cfc707a7ac9bd77d095ff0f8Mike J. Chen             * to determine whether or not to stream lower resolution
10765142031872205241cfc707a7ac9bd77d095ff0f8Mike J. Chen             * videos when the hdmi mode is < 1080p.
10775142031872205241cfc707a7ac9bd77d095ff0f8Mike J. Chen             * otherwise, they'd give us 1080p and we'd just scale it
10785142031872205241cfc707a7ac9bd77d095ff0f8Mike J. Chen             * down to the hdmi mode res.  UI apps are always going
10795142031872205241cfc707a7ac9bd77d095ff0f8Mike J. Chen             * to draw at 1080p and we'll scale down because the
10805142031872205241cfc707a7ac9bd77d095ff0f8Mike J. Chen             * system can't support dynamic dpi changes.
10815142031872205241cfc707a7ac9bd77d095ff0f8Mike J. Chen             */
10825142031872205241cfc707a7ac9bd77d095ff0f8Mike J. Chen            char display[PROPERTY_VALUE_MAX];
10835142031872205241cfc707a7ac9bd77d095ff0f8Mike J. Chen            snprintf(display, sizeof(display), "%dx%d",
10845142031872205241cfc707a7ac9bd77d095ff0f8Mike J. Chen                     d.modedb[best].xres, d.modedb[best].yres);
10855142031872205241cfc707a7ac9bd77d095ff0f8Mike J. Chen            ALOGD("setting property sys.display-size to %s", display);
10865142031872205241cfc707a7ac9bd77d095ff0f8Mike J. Chen            property_set("sys.display-size", display);
10875142031872205241cfc707a7ac9bd77d095ff0f8Mike J. Chen
1088cb64c2be21ad9550b1f5d2b4a8361e997b9be757Lajos Molnar            ioctl(hwc_dev->dsscomp_fd, DSSCIOC_SETUP_DISPLAY, &sdis);
10895142031872205241cfc707a7ac9bd77d095ff0f8Mike J. Chen        }
10904cb51e55fa79a592d50d94c0700660e42c988a0bLajos Molnar        ext->last_mode = ~best;
1091bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar    } else {
1092bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar        __u32 ext_width = d.dis.width_in_mm;
1093bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar        __u32 ext_height = d.dis.height_in_mm;
1094bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar        __u32 ext_fb_xres, ext_fb_yres;
1095bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar
10961b24d08333d1f847e6211aaa1b81f5792aca2704Lajos Molnar        get_max_dimensions(xres, yres, xpy, d.dis.timings.x_res, d.dis.timings.y_res,
1097bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar                           ext_width, ext_height, &ext_fb_xres, &ext_fb_yres);
10984ceb627d195b2efb8cfa3612f38cee211436a7a2Lajos Molnar        if (!d.dis.timings.pixel_clock ||
10990f28098bbd8976f5a182604226da293747ac824bLajos Molnar            d.dis.mgr.interlaced ||
11004ceb627d195b2efb8cfa3612f38cee211436a7a2Lajos Molnar            !omap4_hwc_can_scale(xres, yres, ext_fb_xres, ext_fb_yres,
1101ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar                                 1, &d.dis, &limits,
11024ceb627d195b2efb8cfa3612f38cee211436a7a2Lajos Molnar                                 d.dis.timings.pixel_clock)) {
1103a4e4aeab47b17a82524ac56f2d69daa3e47c1ce7Steve Block            ALOGW("DSS scaler cannot support HDMI cloning");
1104bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar            return -1;
1105bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar        }
1106bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar    }
1107ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    ext->last_xres_used = xres;
1108ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    ext->last_yres_used = yres;
11091b24d08333d1f847e6211aaa1b81f5792aca2704Lajos Molnar    ext->last_xpy = xpy;
1110bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar    if (d.dis.channel == OMAP_DSS_CHANNEL_DIGIT)
1111ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar        ext->on_tv = 1;
1112bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar    return 0;
1113bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar}
1114bd43f27d21c976df59645759598e530ba1a8e01eLajos Molnar
111578fce72baff38f488a0117591d4241d278a48b1bLajos Molnarstruct counts {
111678fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    unsigned int possible_overlay_layers;
111778fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    unsigned int composited_layers;
111878fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    unsigned int scaled_layers;
111978fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    unsigned int RGB;
112078fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    unsigned int BGR;
112178fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    unsigned int NV12;
1122834b8ba01376239a2f286a3766c14bdeeb166498Lajos Molnar    unsigned int dockable;
112344a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar    unsigned int protected;
1124b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar
112578fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    unsigned int max_hw_overlays;
112678fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    unsigned int max_scaling_overlays;
112738934f125a600817dded7aeba9639c6a75afe358Lajos Molnar    unsigned int mem;
112878fce72baff38f488a0117591d4241d278a48b1bLajos Molnar};
112978fce72baff38f488a0117591d4241d278a48b1bLajos Molnar
11306ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFaddenstatic void gather_layer_statistics(omap4_hwc_device_t *hwc_dev, struct counts *num, hwc_display_contents_1_t *list)
113144a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar{
113244a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar    unsigned int i;
113344a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar
113444a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar    /* Figure out how many layers we can support via DSS */
113544a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar    for (i = 0; list && i < list->numHwLayers; i++) {
11366ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden        hwc_layer_1_t *layer = &list->hwLayers[i];
113744a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar        IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
113844a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar
113944a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar        layer->compositionType = HWC_FRAMEBUFFER;
114044a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar
114144a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar        if (omap4_hwc_is_valid_layer(hwc_dev, layer, handle)) {
114244a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar            num->possible_overlay_layers++;
114344a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar
114444a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar            /* NV12 layers can only be rendered on scaling overlays */
1145876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            if (scaled(layer) || is_NV12(handle) || hwc_dev->primary_transform)
114644a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar                num->scaled_layers++;
114744a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar
114844a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar            if (is_BGR(handle))
114944a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar                num->BGR++;
115044a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar            else if (is_RGB(handle))
115144a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar                num->RGB++;
115244a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar            else if (is_NV12(handle))
115344a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar                num->NV12++;
115444a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar
115544a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar            if (dockable(layer))
115644a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar                num->dockable++;
115744a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar
115844a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar            if (is_protected(layer))
115944a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar                num->protected++;
116044a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar
116144a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar            num->mem += mem1d(handle);
116244a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar        }
116344a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar    }
116444a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar}
116544a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar
116644a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnarstatic void decide_supported_cloning(omap4_hwc_device_t *hwc_dev, struct counts *num)
116778fce72baff38f488a0117591d4241d278a48b1bLajos Molnar{
1168ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    omap4_hwc_ext_t *ext = &hwc_dev->ext;
116978fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    int nonscaling_ovls = NUM_NONSCALING_OVERLAYS;
117078fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    num->max_hw_overlays = MAX_HW_OVERLAYS;
117178fce72baff38f488a0117591d4241d278a48b1bLajos Molnar
117278fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    /*
117378fce72baff38f488a0117591d4241d278a48b1bLajos Molnar     * We cannot atomically switch overlays from one display to another.  First, they
117478fce72baff38f488a0117591d4241d278a48b1bLajos Molnar     * have to be disabled, and the disabling has to take effect on the current display.
117578fce72baff38f488a0117591d4241d278a48b1bLajos Molnar     * We keep track of the available number of overlays here.
117678fce72baff38f488a0117591d4241d278a48b1bLajos Molnar     */
11770aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    if (ext->dock.enabled && !(ext->mirror.enabled && !(num->dockable || ext->force_dock))) {
117878fce72baff38f488a0117591d4241d278a48b1bLajos Molnar        /* some overlays may already be used by the external display, so we account for this */
117978fce72baff38f488a0117591d4241d278a48b1bLajos Molnar
118078fce72baff38f488a0117591d4241d278a48b1bLajos Molnar        /* reserve just a video pipeline for HDMI if docking */
11810aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        hwc_dev->ext_ovls = (num->dockable || ext->force_dock) ? 1 : 0;
118278fce72baff38f488a0117591d4241d278a48b1bLajos Molnar        num->max_hw_overlays -= max(hwc_dev->ext_ovls, hwc_dev->last_ext_ovls);
11831b24d08333d1f847e6211aaa1b81f5792aca2704Lajos Molnar
11841b24d08333d1f847e6211aaa1b81f5792aca2704Lajos Molnar        /* use mirroring transform if we are auto-switching to docking mode while mirroring*/
11851b24d08333d1f847e6211aaa1b81f5792aca2704Lajos Molnar        if (ext->mirror.enabled) {
11861b24d08333d1f847e6211aaa1b81f5792aca2704Lajos Molnar            ext->current = ext->mirror;
11871b24d08333d1f847e6211aaa1b81f5792aca2704Lajos Molnar            ext->current.docking = 1;
11881b24d08333d1f847e6211aaa1b81f5792aca2704Lajos Molnar        } else {
11891b24d08333d1f847e6211aaa1b81f5792aca2704Lajos Molnar            ext->current = ext->dock;
11901b24d08333d1f847e6211aaa1b81f5792aca2704Lajos Molnar        }
1191ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    } else if (ext->mirror.enabled) {
119278fce72baff38f488a0117591d4241d278a48b1bLajos Molnar        /*
119378fce72baff38f488a0117591d4241d278a48b1bLajos Molnar         * otherwise, manage just from half the pipelines.  NOTE: there is
119478fce72baff38f488a0117591d4241d278a48b1bLajos Molnar         * no danger of having used too many overlays for external display here.
119578fce72baff38f488a0117591d4241d278a48b1bLajos Molnar         */
11966d94b7785c5318b6de36193a7f5488a88b6178ebDandawate Saket
119778fce72baff38f488a0117591d4241d278a48b1bLajos Molnar        num->max_hw_overlays >>= 1;
119878fce72baff38f488a0117591d4241d278a48b1bLajos Molnar        nonscaling_ovls >>= 1;
119978fce72baff38f488a0117591d4241d278a48b1bLajos Molnar        hwc_dev->ext_ovls = MAX_HW_OVERLAYS - num->max_hw_overlays;
1200ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar        ext->current = ext->mirror;
120178fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    } else {
120278fce72baff38f488a0117591d4241d278a48b1bLajos Molnar        num->max_hw_overlays -= hwc_dev->last_ext_ovls;
120378fce72baff38f488a0117591d4241d278a48b1bLajos Molnar        hwc_dev->ext_ovls = 0;
1204ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar        ext->current.enabled = 0;
120578fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    }
120678fce72baff38f488a0117591d4241d278a48b1bLajos Molnar
120778fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    /*
120878fce72baff38f488a0117591d4241d278a48b1bLajos Molnar     * :TRICKY: We may not have enough overlays on the external display.  We "reserve" them
120978fce72baff38f488a0117591d4241d278a48b1bLajos Molnar     * here to figure out if mirroring is supported, but may not do mirroring for the first
121078fce72baff38f488a0117591d4241d278a48b1bLajos Molnar     * frame while the overlays required for it are cleared.
121178fce72baff38f488a0117591d4241d278a48b1bLajos Molnar     */
1212bd0fe036293115c9f9b182ed2a911bdd557ea491Lajos Molnar    hwc_dev->ext_ovls_wanted = hwc_dev->ext_ovls;
121378fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    hwc_dev->ext_ovls = min(MAX_HW_OVERLAYS - hwc_dev->last_int_ovls, hwc_dev->ext_ovls);
121478fce72baff38f488a0117591d4241d278a48b1bLajos Molnar
1215ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    /* if mirroring, we are limited by both internal and external overlays.  However,
1216ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar       ext_ovls is always <= MAX_HW_OVERLAYS / 2 <= max_hw_overlays */
1217ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    if (hwc_dev->ext_ovls && ext->current.enabled && !ext->current.docking)
1218b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar        num->max_hw_overlays = hwc_dev->ext_ovls;
121978fce72baff38f488a0117591d4241d278a48b1bLajos Molnar
12206d94b7785c5318b6de36193a7f5488a88b6178ebDandawate Saket    /* If FB is not same resolution as LCD don't use GFX pipe line*/
1221876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (hwc_dev->primary_transform) {
1222876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        num->max_hw_overlays -= NUM_NONSCALING_OVERLAYS;
12236d94b7785c5318b6de36193a7f5488a88b6178ebDandawate Saket        num->max_scaling_overlays = num->max_hw_overlays;
1224876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    } else
12255db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket        num->max_scaling_overlays = num->max_hw_overlays - nonscaling_ovls;
122644a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar}
122778fce72baff38f488a0117591d4241d278a48b1bLajos Molnar
122844a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnarstatic int can_dss_render_all(omap4_hwc_device_t *hwc_dev, struct counts *num)
122944a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar{
123044a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar    omap4_hwc_ext_t *ext = &hwc_dev->ext;
12315db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket    int on_tv = hwc_dev->on_tv || (ext->on_tv && ext->current.enabled);
123244a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar    int tform = ext->current.enabled && (ext->current.rotation || ext->current.hflip);
1233ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar
12344b267e18b9e98b788d2b1bf2f1268ed25e5b726dLajos Molnar    return  !hwc_dev->force_sgx &&
12354b267e18b9e98b788d2b1bf2f1268ed25e5b726dLajos Molnar            /* must have at least one layer if using composition bypass to get sync object */
123678fce72baff38f488a0117591d4241d278a48b1bLajos Molnar            num->possible_overlay_layers &&
123778fce72baff38f488a0117591d4241d278a48b1bLajos Molnar            num->possible_overlay_layers <= num->max_hw_overlays &&
123878fce72baff38f488a0117591d4241d278a48b1bLajos Molnar            num->possible_overlay_layers == num->composited_layers &&
123978fce72baff38f488a0117591d4241d278a48b1bLajos Molnar            num->scaled_layers <= num->max_scaling_overlays &&
12404af5978e0677b13118611721f265e2dbaba849ffLajos Molnar            num->NV12 <= num->max_scaling_overlays &&
124138934f125a600817dded7aeba9639c6a75afe358Lajos Molnar            /* fits into TILER slot */
1242876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            num->mem <= limits.tiler1d_slot_size &&
124378fce72baff38f488a0117591d4241d278a48b1bLajos Molnar            /* we cannot clone non-NV12 transformed layers */
124478fce72baff38f488a0117591d4241d278a48b1bLajos Molnar            (!tform || num->NV12 == num->possible_overlay_layers) &&
124578fce72baff38f488a0117591d4241d278a48b1bLajos Molnar            /* HDMI cannot display BGR */
1246ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar            (num->BGR == 0 || (num->RGB == 0 && !on_tv) || !hwc_dev->flags_rgb_order);
124778fce72baff38f488a0117591d4241d278a48b1bLajos Molnar}
124878fce72baff38f488a0117591d4241d278a48b1bLajos Molnar
124978fce72baff38f488a0117591d4241d278a48b1bLajos Molnarstatic inline int can_dss_render_layer(omap4_hwc_device_t *hwc_dev,
12506ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden            hwc_layer_1_t *layer)
125178fce72baff38f488a0117591d4241d278a48b1bLajos Molnar{
125278fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
125378fce72baff38f488a0117591d4241d278a48b1bLajos Molnar
125444a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar    omap4_hwc_ext_t *ext = &hwc_dev->ext;
1255876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    int cloning = ext->current.enabled && (!ext->current.docking || (handle!=NULL ? dockable(layer) : 0));
1256876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    int on_tv = hwc_dev->on_tv || (ext->on_tv && cloning);
1257876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    int tform = cloning && (ext->current.rotation || ext->current.hflip);
125878fce72baff38f488a0117591d4241d278a48b1bLajos Molnar
1259d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar    return omap4_hwc_is_valid_layer(hwc_dev, layer, handle) &&
12602952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar           /* cannot rotate non-NV12 layers on external display */
12615706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar           (!tform || is_NV12(handle)) &&
126278fce72baff38f488a0117591d4241d278a48b1bLajos Molnar           /* skip non-NV12 layers if also using SGX (if nv12_only flag is set) */
12635706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar           (!hwc_dev->flags_nv12_only || (!hwc_dev->use_sgx || is_NV12(handle))) &&
126478fce72baff38f488a0117591d4241d278a48b1bLajos Molnar           /* make sure RGB ordering is consistent (if rgb_order flag is set) */
12655706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar           (!(hwc_dev->swap_rb ? is_RGB(handle) : is_BGR(handle)) ||
126678fce72baff38f488a0117591d4241d278a48b1bLajos Molnar            !hwc_dev->flags_rgb_order) &&
126778fce72baff38f488a0117591d4241d278a48b1bLajos Molnar           /* TV can only render RGB */
12685706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar           !(on_tv && is_BGR(handle));
126978fce72baff38f488a0117591d4241d278a48b1bLajos Molnar}
127078fce72baff38f488a0117591d4241d278a48b1bLajos Molnar
1271834b8ba01376239a2f286a3766c14bdeeb166498Lajos Molnarstatic inline int display_area(struct dss2_ovl_info *o)
1272834b8ba01376239a2f286a3766c14bdeeb166498Lajos Molnar{
1273834b8ba01376239a2f286a3766c14bdeeb166498Lajos Molnar    return o->cfg.win.w * o->cfg.win.h;
1274834b8ba01376239a2f286a3766c14bdeeb166498Lajos Molnar}
1275834b8ba01376239a2f286a3766c14bdeeb166498Lajos Molnar
12763837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnarstatic int clone_layer(omap4_hwc_device_t *hwc_dev, int ix) {
1277876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->comp_data.dsscomp_data;
12783837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    omap4_hwc_ext_t *ext = &hwc_dev->ext;
12793837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    int ext_ovl_ix = dsscomp->num_ovls - hwc_dev->post2_layers;
12803837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    struct dss2_ovl_info *o = &dsscomp->ovls[dsscomp->num_ovls];
12813837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar
12823837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    if (dsscomp->num_ovls >= MAX_HW_OVERLAYS) {
128346de639b23db99d7b99ff1c676ac98b84b6336c6Steve Block        ALOGE("**** cannot clone layer #%d. using all %d overlays.", ix, dsscomp->num_ovls);
12843837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar        return -EBUSY;
12853837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    }
12863837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar
12873837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    memcpy(o, dsscomp->ovls + ix, sizeof(*o));
12883837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar
12893837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    /* reserve overlays at end for other display */
12903837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    o->cfg.ix = MAX_HW_OVERLAYS - 1 - ext_ovl_ix;
12913837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    o->cfg.mgr_ix = 1;
129212c821dbf70ee94bd9702e7cb60c66c8156c83d6Erik Gilling    o->addressing = OMAP_DSS_BUFADDR_OVL_IX;
12933837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    o->ba = ix;
12943837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar
12953837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    /* use distinct z values (to simplify z-order checking) */
12963837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    o->cfg.zorder += hwc_dev->post2_layers;
12973837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar
12983837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    omap4_hwc_adjust_ext_layer(&hwc_dev->ext, o);
12993837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    dsscomp->num_ovls++;
13003837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    return 0;
13013837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar}
13023837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar
13033837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnarstatic int clone_external_layer(omap4_hwc_device_t *hwc_dev, int ix) {
1304876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->comp_data.dsscomp_data;
13053837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    omap4_hwc_ext_t *ext = &hwc_dev->ext;
13063837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar
13073837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    /* mirror only 1 external layer */
13083837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    struct dss2_ovl_info *o = &dsscomp->ovls[ix];
13093837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar
13103837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    /* full screen video after transformation */
13113837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    __u32 xres = o->cfg.crop.w, yres = o->cfg.crop.h;
13123837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    if ((ext->current.rotation + o->cfg.rotation) & 1)
13133837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar        swap(xres, yres);
13143837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    float xpy = ext->lcd_xpy * o->cfg.win.w / o->cfg.win.h;
13153837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    if (o->cfg.rotation & 1)
13163837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar        xpy = o->cfg.crop.h / xpy / o->cfg.crop.w;
13173837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    else
13183837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar        xpy = o->cfg.crop.h * xpy / o->cfg.crop.w;
13193837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    if (ext->current.rotation & 1)
13203837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar        xpy = 1. / xpy;
13213837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar
13223837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    /* adjust hdmi mode based on resolution */
13233837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    if (xres != ext->last_xres_used ||
13243837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar        yres != ext->last_yres_used ||
13253837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar        xpy < ext->last_xpy * (1.f - ASPECT_RATIO_TOLERANCE) ||
13263837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar        xpy * (1.f - ASPECT_RATIO_TOLERANCE) > ext->last_xpy) {
13273a7df2c042eb8c7289e24e77dd316f73bd0c456fSteve Block        ALOGD("set up HDMI for %d*%d\n", xres, yres);
13283837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar        if (omap4_hwc_set_best_hdmi_mode(hwc_dev, xres, yres, xpy)) {
13293837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar            ext->current.enabled = 0;
13303837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar            return -ENODEV;
13313837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar        }
13323837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    }
13333837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar
13343837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    struct hwc_rect region = {
13353837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar        .left = o->cfg.win.x, .top = o->cfg.win.y,
13363837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar        .right = o->cfg.win.x + o->cfg.win.w,
13373837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar        .bottom = o->cfg.win.y + o->cfg.win.h
13383837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    };
13393837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    set_ext_matrix(&hwc_dev->ext, region);
13403837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar
13413837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    return clone_layer(hwc_dev, ix);
13423837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar}
13433837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar
13443837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnarstatic int setup_mirroring(omap4_hwc_device_t *hwc_dev)
13453837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar{
13463837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    omap4_hwc_ext_t *ext = &hwc_dev->ext;
13473837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar
13483837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    __u32 xres = WIDTH(ext->mirror_region);
13493837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    __u32 yres = HEIGHT(ext->mirror_region);
13503837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    if (ext->current.rotation & 1)
13513837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar       swap(xres, yres);
13523837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    if (omap4_hwc_set_best_hdmi_mode(hwc_dev, xres, yres, ext->lcd_xpy))
13533837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar        return -ENODEV;
13543837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    set_ext_matrix(ext, ext->mirror_region);
13553837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    return 0;
13563837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar}
13573837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar
13586ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden/*
13596ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden * We're using "implicit" synchronization, so make sure we aren't passing any
13606ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden * sync object descriptors around.
13616ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden */
13626ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFaddenstatic void check_sync_fds(size_t numDisplays, hwc_display_contents_1_t** displays)
13636ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden{
13646ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden    //ALOGD("checking sync FDs");
13656ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden    unsigned int i, j;
13666ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden    for (i = 0; i < numDisplays; i++) {
13676ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden        hwc_display_contents_1_t* list = displays[i];
13683d6b69f0a0fb325443ef8c2987c16af1f8618d3eJesse Hall        if (list->retireFenceFd >= 0) {
13693d6b69f0a0fb325443ef8c2987c16af1f8618d3eJesse Hall            ALOGW("retireFenceFd[%u] was %d", i, list->retireFenceFd);
13703d6b69f0a0fb325443ef8c2987c16af1f8618d3eJesse Hall            list->retireFenceFd = -1;
13716ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden        }
13726ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden
13736ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden        for (j = 0; j < list->numHwLayers; j++) {
13746ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden            hwc_layer_1_t* layer = &list->hwLayers[j];
13756ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden            if (layer->acquireFenceFd >= 0) {
13766ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden                ALOGW("acquireFenceFd[%u][%u] was %d, closing", i, j, layer->acquireFenceFd);
13776ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden                close(layer->acquireFenceFd);
13786ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden                layer->acquireFenceFd = -1;
13796ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden            }
13806ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden            if (layer->releaseFenceFd >= 0) {
13816ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden                ALOGW("releaseFenceFd[%u][%u] was %d", i, j, layer->releaseFenceFd);
13826ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden                layer->releaseFenceFd = -1;
13836ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden            }
13846ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden        }
13856ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden    }
13866ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden}
13876ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden
1388fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht/* test if layer appears to be RGB32 (4 Bpp) and > 1280x720 */
1389fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrechtstatic int is_large_rgb32_layer(const hwc_layer_1_t *layer)
1390fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht{
1391fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht    IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
1392fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht
1393fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht    return is_RGB32(handle) &&
1394fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht        (((layer->sourceCrop.right - layer->sourceCrop.left) > 1280) ||
1395fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht        ((layer->sourceCrop.bottom - layer->sourceCrop.top) > 720));
1396fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht}
1397fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht
1398876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chenstatic void blit_reset(omap4_hwc_device_t *hwc_dev, int flags)
1399876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen{
1400876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    hwc_dev->blit_flags = 0;
1401876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    hwc_dev->blit_num = 0;
1402876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    hwc_dev->post2_blit_buffers = 0;
1403876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    hwc_dev->comp_data.blit_data.rgz_items = 0;
1404876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1405876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    /* We want to maintain the rgz dirty region data if there are no geometry changes */
1406876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (flags & HWC_GEOMETRY_CHANGED)
1407876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        rgz_release(&grgz);
1408876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen}
1409876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1410876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chenstatic int blit_layers(omap4_hwc_device_t *hwc_dev, hwc_layer_list_t *list, int bufoff)
1411876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen{
1412876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    /* Do not blit if this frame will be composed entirely by the GPU */
1413876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (!list || hwc_dev->force_sgx)
1414876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        goto err_out;
1415876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1416876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    int rgz_in_op;
1417876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    int rgz_out_op;
1418876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1419876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    switch (hwc_dev->blt_mode) {
1420876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        case BLTMODE_PAINT:
1421876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            rgz_in_op = RGZ_IN_HWCCHK;
1422876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            rgz_out_op = RGZ_OUT_BVCMD_PAINT;
1423876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            break;
1424876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        case BLTMODE_REGION:
1425876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        default:
1426876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            rgz_in_op = RGZ_IN_HWC;
1427876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            rgz_out_op = RGZ_OUT_BVCMD_REGION;
1428876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            break;
1429876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    }
1430876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1431876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    rgz_in_params_t in = {
1432876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        .op = rgz_in_op,
1433876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        .data = {
1434876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            .hwc = {
1435876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                .dstgeom = &gscrngeom,
1436876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                .layers = list->hwLayers,
1437876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                .layerno = list->numHwLayers
1438876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            }
1439876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        }
1440876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    };
1441876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1442876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    /*
1443876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen     * This means if all the layers marked for the FRAMEBUFFER cannot be
1444876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen     * blitted, do not blit, for e.g. SKIP layers
1445876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen     */
1446876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (rgz_in(&in, &grgz) != RGZ_ALL)
1447876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        goto err_out;
1448876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1449876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    unsigned int i, count = 0;
1450876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    for (i = 0; i < list->numHwLayers; i++) {
1451876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        if (list->hwLayers[i].compositionType != HWC_OVERLAY) {
1452876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            count++;
1453876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        }
1454876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    }
1455876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1456876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    rgz_out_params_t out = {
1457876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        .op = rgz_out_op,
1458876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        .data = {
1459876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            .bvc = {
1460876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                .dstgeom = &gscrngeom,
1461876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                .noblend = 0,
1462876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            }
1463876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        }
1464876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    };
1465876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1466876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (rgz_out(&grgz, &out) != 0) {
1467876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        ALOGE("Failed generating blits");
1468876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        goto err_out;
1469876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    }
1470876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1471876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    /* This is a special situation where the regionizer decided no blits are
1472876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen     * needed for this frame but there are blit buffers to synchronize with. Can
1473876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen     * happen only if the regionizer is enabled otherwise it's likely a bug
1474876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen     */
1475876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (rgz_out_op != RGZ_OUT_BVCMD_REGION && out.data.bvc.out_blits == 0 && out.data.bvc.out_nhndls > 0) {
1476876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        ALOGE("Regionizer invalid output blit_num %d, post2_blit_buffers %d", out.data.bvc.out_blits, out.data.bvc.out_nhndls);
1477876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        goto err_out;
1478876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    }
1479876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1480876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    hwc_dev->blit_flags |= HWC_BLT_FLAG_USE_FB;
1481876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    hwc_dev->blit_num = out.data.bvc.out_blits;
1482876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    hwc_dev->post2_blit_buffers = out.data.bvc.out_nhndls;
1483876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    for (i = 0; i < hwc_dev->post2_blit_buffers; i++) {
1484876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        //ALOGI("blit buffers[%d] = %p", bufoff, out.data.bvc.out_hndls[i]);
1485876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        hwc_dev->buffers[bufoff++] = out.data.bvc.out_hndls[i];
1486876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    }
1487876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1488876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    struct rgz_blt_entry *res_blit_ops = (struct rgz_blt_entry *) out.data.bvc.cmdp;
1489876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    memcpy(hwc_dev->comp_data.blit_data.rgz_blts, res_blit_ops, sizeof(*res_blit_ops) * out.data.bvc.cmdlen);
1490876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    ALOGI_IF(debugblt, "blt struct sz %d", sizeof(*res_blit_ops) * out.data.bvc.cmdlen);
1491876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    ALOGE_IF(hwc_dev->blit_num != out.data.bvc.cmdlen,"blit_num != out.data.bvc.cmdlen, %d != %d", hwc_dev->blit_num, out.data.bvc.cmdlen);
1492876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1493876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    /* all layers will be rendered without SGX help either via DSS or blitter */
1494876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    for (i = 0; i < list->numHwLayers; i++) {
1495876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        if (list->hwLayers[i].compositionType != HWC_OVERLAY) {
1496876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            list->hwLayers[i].compositionType = HWC_OVERLAY;
1497876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            //ALOGI("blitting layer %d", i);
1498876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        }
1499876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        list->hwLayers[i].hints &= ~HWC_HINT_CLEAR_FB;
1500876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    }
1501876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    return 1;
1502876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1503876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chenerr_out:
1504876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    rgz_release(&grgz);
1505876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    return 0;
1506876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen}
1507876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1508876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chenvoid debug_post2(omap4_hwc_device_t *hwc_dev, int nbufs)
1509876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen{
1510876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (!debugpost2)
1511876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        return;
1512876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->comp_data.dsscomp_data;
1513876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    int i;
1514876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    for (i=0; i<nbufs; i++) {
1515876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        ALOGI("buf[%d] hndl %p", i, hwc_dev->buffers[i]);
1516876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    }
1517876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    for (i=0; i < dsscomp->num_ovls; i++) {
1518876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        ALOGI("ovl[%d] ba %d", i, dsscomp->ovls[i].ba);
1519876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    }
1520876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen}
1521876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
15226ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFaddenstatic int omap4_hwc_prepare(struct hwc_composer_device_1 *dev, size_t numDisplays,
15236ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden        hwc_display_contents_1_t** displays)
1524c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
15256ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden    if (!numDisplays || displays == NULL) {
15266ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden        return 0;
15276ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden    }
15286ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden
15296ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden    hwc_display_contents_1_t* list = displays[0];  // ignore displays beyond the first
1530c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev;
1531876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->comp_data.dsscomp_data;
15320b62b7ca3c6430caaebb2d3815642b2ff80f527aLajos Molnar    struct counts num = { .composited_layers = list ? list->numHwLayers : 0 };
15333837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    unsigned int i, ix;
1534c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
15352125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    pthread_mutex_lock(&hwc_dev->lock);
1536c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    memset(dsscomp, 0x0, sizeof(*dsscomp));
1537c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    dsscomp->sync_id = sync_id++;
1538c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
153944a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar    gather_layer_statistics(hwc_dev, &num, list);
1540834b8ba01376239a2f286a3766c14bdeeb166498Lajos Molnar
154144a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar    decide_supported_cloning(hwc_dev, &num);
1542c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
15434b267e18b9e98b788d2b1bf2f1268ed25e5b726dLajos Molnar    /* Disable the forced SGX rendering if there is only one layer */
15444b267e18b9e98b788d2b1bf2f1268ed25e5b726dLajos Molnar    if (hwc_dev->force_sgx && num.composited_layers <= 1)
15454b267e18b9e98b788d2b1bf2f1268ed25e5b726dLajos Molnar        hwc_dev->force_sgx = 0;
15464b267e18b9e98b788d2b1bf2f1268ed25e5b726dLajos Molnar
154778fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    /* phase 3 logic */
15484b267e18b9e98b788d2b1bf2f1268ed25e5b726dLajos Molnar    if (can_dss_render_all(hwc_dev, &num)) {
1549c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        /* All layers can be handled by the DSS -- don't use SGX for composition */
1550c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        hwc_dev->use_sgx = 0;
155178fce72baff38f488a0117591d4241d278a48b1bLajos Molnar        hwc_dev->swap_rb = num.BGR != 0;
1552c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    } else {
1553c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        /* Use SGX for composition plus first 3 layers that are DSS renderable */
1554c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        hwc_dev->use_sgx = 1;
15555706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar        hwc_dev->swap_rb = is_BGR_format(hwc_dev->fb_dev->base.format);
1556c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    }
1557c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
1558c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    /* setup pipes */
1559c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    int z = 0;
1560a51ba32b3ed323a74235d28a6cb0f31e51d8e514Lajos Molnar    int fb_z = -1;
1561c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    int scaled_gfx = 0;
1562834b8ba01376239a2f286a3766c14bdeeb166498Lajos Molnar    int ix_docking = -1;
1563fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht    int big_layers = 0;
1564c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
1565876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    int blit_all = 0;
1566876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    blit_reset(hwc_dev, list->flags);
1567876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1568876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    /* If the SGX is used or we are going to blit something we need a framebuffer
1569876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen     * and a DSS pipe
1570876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen     */
1571876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    int needs_fb = hwc_dev->use_sgx;
1572876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1573876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (hwc_dev->blt_policy == BLTPOLICY_ALL) {
1574876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        /* Check if we can blit everything */
1575876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        blit_all = blit_layers(hwc_dev, list, 0);
1576876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        if (blit_all) {
1577876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            needs_fb = 1;
1578876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            hwc_dev->use_sgx = 0;
1579876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        }
1580876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    }
1581876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1582876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    /* If a framebuffer is needed, begin using VID1 for DSS overlay layers,
1583876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen     * we need GFX for FB
1584876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen     */
1585876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    dsscomp->num_ovls = needs_fb ? 1 /*VID1*/ : 0 /*GFX*/;
1586876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1587c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    /* set up if DSS layers */
158838934f125a600817dded7aeba9639c6a75afe358Lajos Molnar    unsigned int mem_used = 0;
1589b81fb68ce4c70170ebc9e41f9fe4540cc05685d5Lajos Molnar    hwc_dev->ovls_blending = 0;
1590876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    for (i = 0; list && i < list->numHwLayers && !blit_all; i++) {
15916ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden        hwc_layer_1_t *layer = &list->hwLayers[i];
1592c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
1593c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
15944b267e18b9e98b788d2b1bf2f1268ed25e5b726dLajos Molnar        if (dsscomp->num_ovls < num.max_hw_overlays &&
1595a1be32cc5c3978f9bac62c3b40a257bba2315861Lajos Molnar            can_dss_render_layer(hwc_dev, layer) &&
15964b267e18b9e98b788d2b1bf2f1268ed25e5b726dLajos Molnar            (!hwc_dev->force_sgx ||
15974b267e18b9e98b788d2b1bf2f1268ed25e5b726dLajos Molnar             /* render protected and dockable layers via DSS */
15985706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar             is_protected(layer) ||
15994b267e18b9e98b788d2b1bf2f1268ed25e5b726dLajos Molnar             (hwc_dev->ext.current.docking && hwc_dev->ext.current.enabled && dockable(layer))) &&
1600876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            mem_used + mem1d(handle) < limits.tiler1d_slot_size &&
1601c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            /* can't have a transparent overlay in the middle of the framebuffer stack */
1602fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht            !(is_BLENDED(layer) && fb_z >= 0) &&
1603fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht            /* current hardware is unable to keep up with more than 1 'large' RGB32 layer */
1604fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht            !(is_large_rgb32_layer(layer) && big_layers > 0)) {
16055706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar
1606c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            /* render via DSS overlay */
160738934f125a600817dded7aeba9639c6a75afe358Lajos Molnar            mem_used += mem1d(handle);
1608c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            layer->compositionType = HWC_OVERLAY;
1609b81fb68ce4c70170ebc9e41f9fe4540cc05685d5Lajos Molnar
1610b81fb68ce4c70170ebc9e41f9fe4540cc05685d5Lajos Molnar            /* clear FB above all opaque layers if rendering via SGX */
1611b81fb68ce4c70170ebc9e41f9fe4540cc05685d5Lajos Molnar            if (hwc_dev->use_sgx && !is_BLENDED(layer))
1612b81fb68ce4c70170ebc9e41f9fe4540cc05685d5Lajos Molnar                layer->hints |= HWC_HINT_CLEAR_FB;
1613b81fb68ce4c70170ebc9e41f9fe4540cc05685d5Lajos Molnar            /* see if any of the (non-backmost) overlays are doing blending */
1614b81fb68ce4c70170ebc9e41f9fe4540cc05685d5Lajos Molnar            else if (is_BLENDED(layer) && i > 0)
1615b81fb68ce4c70170ebc9e41f9fe4540cc05685d5Lajos Molnar                hwc_dev->ovls_blending = 1;
1616b81fb68ce4c70170ebc9e41f9fe4540cc05685d5Lajos Molnar
1617e055e4bf77e6c429d7a159e8e853974d9dfc57adLajos Molnar            hwc_dev->buffers[dsscomp->num_ovls] = layer->handle;
1618c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
1619c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            omap4_hwc_setup_layer(hwc_dev,
1620c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                                  &dsscomp->ovls[dsscomp->num_ovls],
1621f1e357b2cf26fa5a50789061e068e4f0bd4ea772Mathias Agopian                                  layer,
1622c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                                  z,
1623c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                                  handle->iFormat,
1624c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                                  handle->iWidth,
1625c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                                  handle->iHeight);
1626d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar
1627876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            dsscomp->ovls[dsscomp->num_ovls].cfg.ix = dsscomp->num_ovls + hwc_dev->primary_transform;
162812c821dbf70ee94bd9702e7cb60c66c8156c83d6Erik Gilling            dsscomp->ovls[dsscomp->num_ovls].addressing = OMAP_DSS_BUFADDR_LAYER_IX;
162912c821dbf70ee94bd9702e7cb60c66c8156c83d6Erik Gilling            dsscomp->ovls[dsscomp->num_ovls].ba = dsscomp->num_ovls;
1630c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
1631c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            /* ensure GFX layer is never scaled */
1632876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            if ((dsscomp->num_ovls == 0) && (!hwc_dev->primary_transform)) {
1633876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                scaled_gfx = scaled(layer) || is_NV12(handle);
1634876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            } else if (scaled_gfx && !scaled(layer) && !is_NV12(handle)) {
1635c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                /* swap GFX layer with this one */
1636c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                dsscomp->ovls[dsscomp->num_ovls].cfg.ix = 0;
1637876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                dsscomp->ovls[0].cfg.ix = dsscomp->num_ovls;
1638c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                scaled_gfx = 0;
1639c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            }
1640c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
1641834b8ba01376239a2f286a3766c14bdeeb166498Lajos Molnar            /* remember largest dockable layer */
1642834b8ba01376239a2f286a3766c14bdeeb166498Lajos Molnar            if (dockable(layer) &&
1643834b8ba01376239a2f286a3766c14bdeeb166498Lajos Molnar                (ix_docking < 0 ||
164400d8485d3d319633f410e52cab1562fe165af1e3Lajos Molnar                 display_area(&dsscomp->ovls[dsscomp->num_ovls]) > display_area(&dsscomp->ovls[ix_docking])))
1645834b8ba01376239a2f286a3766c14bdeeb166498Lajos Molnar                ix_docking = dsscomp->num_ovls;
164678fce72baff38f488a0117591d4241d278a48b1bLajos Molnar
1647c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            dsscomp->num_ovls++;
1648c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            z++;
1649fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht
1650fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht            /* record whether or not this was a 'big' RGB32 layer */
1651fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht            if (is_large_rgb32_layer(layer)) {
1652fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht                big_layers++;
1653fc13c9292160e3eb83fe5b4f191d1ccee2fd67d9Travis Geiselbrecht            }
1654c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        } else if (hwc_dev->use_sgx) {
1655c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            if (fb_z < 0) {
1656c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                /* NOTE: we are not handling transparent cutout for now */
1657a51ba32b3ed323a74235d28a6cb0f31e51d8e514Lajos Molnar                fb_z = z;
1658c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                z++;
1659c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            } else {
1660c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                /* move fb z-order up (by lowering dss layers) */
1661a51ba32b3ed323a74235d28a6cb0f31e51d8e514Lajos Molnar                while (fb_z < z - 1)
1662a51ba32b3ed323a74235d28a6cb0f31e51d8e514Lajos Molnar                    dsscomp->ovls[1 + fb_z++].cfg.zorder--;
1663c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            }
1664c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
1665c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    }
1666c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
1667c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    /* if scaling GFX (e.g. only 1 scaled surface) use a VID pipe */
1668c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if (scaled_gfx)
1669876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        dsscomp->ovls[0].cfg.ix = dsscomp->num_ovls;
1670876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1671876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (hwc_dev->blt_policy == BLTPOLICY_DEFAULT) {
1672876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        if (hwc_dev->use_sgx) {
1673876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            if (blit_layers(hwc_dev, list, dsscomp->num_ovls == 1 ? 0 : dsscomp->num_ovls)) {
1674876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                hwc_dev->use_sgx = 0;
1675876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            }
1676876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        }
1677876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    }
1678c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
1679876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    /* If the SGX is not used and there is blit data we need a framebuffer and
1680876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen     * a DSS pipe well configured for it
1681876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen     */
1682876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (needs_fb) {
1683b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar        /* assign a z-layer for fb */
1684449e98a958753e6ae8f16b923596af0c6783ff8aLajos Molnar        if (fb_z < 0) {
1685876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            if (!hwc_dev->blt_policy != BLTPOLICY_DISABLED && num.composited_layers)
16866d94b7785c5318b6de36193a7f5488a88b6178ebDandawate Saket                ALOGE("**** should have assigned z-layer for fb");
1687449e98a958753e6ae8f16b923596af0c6783ff8aLajos Molnar            fb_z = z++;
1688449e98a958753e6ae8f16b923596af0c6783ff8aLajos Molnar        }
1689876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        /*
1690876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen         * This is needed because if we blit all we would lose the handle of
1691876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen         * the first layer
1692876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen         */
1693876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        if (hwc_dev->blit_num == 0) {
1694876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            hwc_dev->buffers[0] = NULL;
1695876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        }
1696c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        omap4_hwc_setup_layer_base(&dsscomp->ovls[0].cfg, fb_z,
1697c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                                   hwc_dev->fb_dev->base.format,
16985706ba0da054830e63b82b195ec32a97c390bd2cLajos Molnar                                   1,   /* FB is always premultiplied */
1699c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                                   hwc_dev->fb_dev->base.width,
1700c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                                   hwc_dev->fb_dev->base.height);
1701c35f8ef2dc4bf1606f2b27f750057b12e51cb99aErik Gilling        dsscomp->ovls[0].cfg.pre_mult_alpha = 1;
170212c821dbf70ee94bd9702e7cb60c66c8156c83d6Erik Gilling        dsscomp->ovls[0].addressing = OMAP_DSS_BUFADDR_LAYER_IX;
170312c821dbf70ee94bd9702e7cb60c66c8156c83d6Erik Gilling        dsscomp->ovls[0].ba = 0;
1704876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        dsscomp->ovls[0].cfg.ix = hwc_dev->primary_transform;
1705c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    }
1706c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
170778fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    /* mirror layers */
170878fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    hwc_dev->post2_layers = dsscomp->num_ovls;
17093837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar
17103837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    omap4_hwc_ext_t *ext = &hwc_dev->ext;
17113837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    if (ext->current.enabled && hwc_dev->ext_ovls) {
17123837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar        if (ext->current.docking && ix_docking >= 0) {
1713876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            if (clone_external_layer(hwc_dev, ix_docking) == 0)
171412c821dbf70ee94bd9702e7cb60c66c8156c83d6Erik Gilling                dsscomp->ovls[dsscomp->num_ovls - 1].cfg.zorder = z++;
17150aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        } else if (ext->current.docking && ix_docking < 0 && ext->force_dock) {
17160aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar            ix_docking = dsscomp->num_ovls;
17170aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar            struct dss2_ovl_info *oi = &dsscomp->ovls[ix_docking];
17180aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar            omap4_hwc_setup_layer_base(&oi->cfg, 0, HAL_PIXEL_FORMAT_BGRA_8888, 1,
17190aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar                                       dock_image.width, dock_image.height);
17200aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar            oi->cfg.stride = dock_image.rowbytes;
17210aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar            if (clone_external_layer(hwc_dev, ix_docking) == 0) {
17220aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar                oi->addressing = OMAP_DSS_BUFADDR_FB;
17230aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar                oi->ba = 0;
17240aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar                z++;
17250aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar            }
17263837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar        } else if (!ext->current.docking) {
17273837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar            int res = 0;
1728834b8ba01376239a2f286a3766c14bdeeb166498Lajos Molnar
1729834b8ba01376239a2f286a3766c14bdeeb166498Lajos Molnar            /* reset mode if we are coming from docking */
17303837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar            if (ext->last.docking)
17313837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar                res = setup_mirroring(hwc_dev);
1732c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
17333837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar            /* mirror all layers */
17343837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar            for (ix = 0; res == 0 && ix < hwc_dev->post2_layers; ix++) {
17353837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar                if (clone_layer(hwc_dev, ix))
17363837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar                    break;
17373837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar                z++;
17382952fd7510718abf21a5fc6d683fd1b4a6025171Lajos Molnar            }
173978fce72baff38f488a0117591d4241d278a48b1bLajos Molnar        }
174078fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    }
1741876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1742876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    /* Apply transform for primary display */
1743876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (hwc_dev->primary_transform)
1744876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        for (i = 0; i < dsscomp->num_ovls; i++) {
1745876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            if(dsscomp->ovls[i].cfg.mgr_ix == 0)
1746876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                omap4_hwc_adjust_primary_display_layer(hwc_dev, &dsscomp->ovls[i]);
1747876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        }
1748876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
17493837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    ext->last = ext->current;
175078fce72baff38f488a0117591d4241d278a48b1bLajos Molnar
175178fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    if (z != dsscomp->num_ovls || dsscomp->num_ovls > MAX_HW_OVERLAYS)
175246de639b23db99d7b99ff1c676ac98b84b6336c6Steve Block        ALOGE("**** used %d z-layers for %d overlays\n", z, dsscomp->num_ovls);
175378fce72baff38f488a0117591d4241d278a48b1bLajos Molnar
175444a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar    /* verify all z-orders and overlay indices are distinct */
175544a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar    for (i = z = ix = 0; i < dsscomp->num_ovls; i++) {
175644a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar        struct dss2_ovl_cfg *c = &dsscomp->ovls[i].cfg;
175744a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar
175844a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar        if (z & (1 << c->zorder))
175946de639b23db99d7b99ff1c676ac98b84b6336c6Steve Block            ALOGE("**** used z-order #%d multiple times", c->zorder);
176044a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar        if (ix & (1 << c->ix))
176146de639b23db99d7b99ff1c676ac98b84b6336c6Steve Block            ALOGE("**** used ovl index #%d multiple times", c->ix);
176244a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar        z |= 1 << c->zorder;
176344a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar        ix |= 1 << c->ix;
176444a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar    }
176578fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    dsscomp->mode = DSSCOMP_SETUP_DISPLAY;
176678fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    dsscomp->mgrs[0].ix = 0;
176778fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    dsscomp->mgrs[0].alpha_blending = 1;
176878fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    dsscomp->mgrs[0].swap_rb = hwc_dev->swap_rb;
176978fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    dsscomp->num_mgrs = 1;
177078fce72baff38f488a0117591d4241d278a48b1bLajos Molnar
17713837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar    if (ext->current.enabled || hwc_dev->last_ext_ovls) {
177278fce72baff38f488a0117591d4241d278a48b1bLajos Molnar        dsscomp->mgrs[1] = dsscomp->mgrs[0];
177378fce72baff38f488a0117591d4241d278a48b1bLajos Molnar        dsscomp->mgrs[1].ix = 1;
177478fce72baff38f488a0117591d4241d278a48b1bLajos Molnar        dsscomp->num_mgrs++;
177578fce72baff38f488a0117591d4241d278a48b1bLajos Molnar        hwc_dev->ext_ovls = dsscomp->num_ovls - hwc_dev->post2_layers;
177678fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    }
177744a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar
177844a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar    if (debug) {
17793a7df2c042eb8c7289e24e77dd316f73bd0c456fSteve Block        ALOGD("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",
178044a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar             dsscomp->sync_id,
178144a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar             hwc_dev->use_sgx ? "SGX+OVL" : "all-OVL",
178244a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar             num.composited_layers,
178344a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar             num.possible_overlay_layers, num.scaled_layers,
178444a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar             num.RGB, num.BGR, num.NV12,
178544a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar             ext->on_tv ? "tv+" : "",
178644a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar             ext->current.enabled ? ext->current.docking ? "dock+" : "mirror+" : "OFF+",
178744a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar             ext->current.rotation * 90,
178844a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar             ext->current.hflip ? "+hflip" : "",
178944a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar             hwc_dev->ext_ovls, num.max_hw_overlays, hwc_dev->last_ext_ovls, hwc_dev->last_int_ovls);
179044a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar    }
179144a0023db5b752a81fb0bd3badd4cca1a1c4edc0Lajos Molnar
17922125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    pthread_mutex_unlock(&hwc_dev->lock);
1793c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    return 0;
1794c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
1795c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
179624a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnarstatic void omap4_hwc_reset_screen(omap4_hwc_device_t *hwc_dev)
179724a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar{
179824a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar    static int first_set = 1;
179924a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar    int ret;
180024a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar
180124a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar    if (first_set) {
180224a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar        first_set = 0;
180324a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar        struct dsscomp_setup_dispc_data d = {
1804b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar            .num_mgrs = 1,
180524a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar        };
180624a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar        /* remove bootloader image from the screen as blank/unblank does not change the composition */
1807cb64c2be21ad9550b1f5d2b4a8361e997b9be757Lajos Molnar        ret = ioctl(hwc_dev->dsscomp_fd, DSSCIOC_SETUP_DISPC, &d);
180824a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar        if (ret)
1809a4e4aeab47b17a82524ac56f2d69daa3e47c1ce7Steve Block            ALOGW("failed to remove bootloader image");
181024a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar
181124a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar        /* blank and unblank fd to make sure display is properly programmed on boot.
181224a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar         * This is needed because the bootloader can not be trusted.
181324a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar         */
181424a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar        ret = ioctl(hwc_dev->fb_fd, FBIOBLANK, FB_BLANK_POWERDOWN);
181524a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar        if (ret)
1816a4e4aeab47b17a82524ac56f2d69daa3e47c1ce7Steve Block            ALOGW("failed to blank display");
181724a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar
181824a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar        ret = ioctl(hwc_dev->fb_fd, FBIOBLANK, FB_BLANK_UNBLANK);
181924a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar        if (ret)
1820a4e4aeab47b17a82524ac56f2d69daa3e47c1ce7Steve Block            ALOGW("failed to blank display");
182124a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar    }
182224a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar}
182324a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar
18246ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFaddenstatic int omap4_hwc_set(struct hwc_composer_device_1 *dev,
18256ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden        size_t numDisplays, hwc_display_contents_1_t** displays)
1826c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
18276ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden    if (!numDisplays || displays == NULL) {
18286ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden        ALOGD("set: empty display list");
18296ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden        return 0;
18306ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden    }
18316ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden    hwc_display_t dpy = NULL;
18326ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden    hwc_surface_t sur = NULL;
18336ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden    hwc_display_contents_1_t* list = displays[0];  // ignore displays beyond the first
18346ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden    if (list != NULL) {
18356ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden        dpy = list->dpy;
18366ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden        sur = list->sur;
18376ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden    }
1838c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev;
1839876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->comp_data.dsscomp_data;
1840ee0725d529a6adced20dd0182f9fd470607ce495Lajos Molnar    int err = 0;
1841bd0fe036293115c9f9b182ed2a911bdd557ea491Lajos Molnar    int invalidate;
1842c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
18432125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    pthread_mutex_lock(&hwc_dev->lock);
184424a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar
184527843d0acbb3d17ec4458900b6cd5e281a464611Travis Geiselbrecht    /* disable resetting the screen on the first boot for devices
184627843d0acbb3d17ec4458900b6cd5e281a464611Travis Geiselbrecht     * with hdmi as primary input.
184727843d0acbb3d17ec4458900b6cd5e281a464611Travis Geiselbrecht     */
184827843d0acbb3d17ec4458900b6cd5e281a464611Travis Geiselbrecht    if (!hwc_dev->on_tv)
184927843d0acbb3d17ec4458900b6cd5e281a464611Travis Geiselbrecht        omap4_hwc_reset_screen(hwc_dev);
185024a18d2f746877f2abd63e95b4be9c54dac4472eLajos Molnar
1851bd0fe036293115c9f9b182ed2a911bdd557ea491Lajos Molnar    invalidate = hwc_dev->ext_ovls_wanted && !hwc_dev->ext_ovls;
1852bd0fe036293115c9f9b182ed2a911bdd557ea491Lajos Molnar
1853734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    if (debug)
1854734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        dump_set_info(hwc_dev, list);
1855c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
1856ee0725d529a6adced20dd0182f9fd470607ce495Lajos Molnar    if (dpy && sur) {
1857e37a11c21bcac1fbcac995cd34884eac37492b95Mathias Agopian        // list can be NULL which means hwc is temporarily disabled.
1858e37a11c21bcac1fbcac995cd34884eac37492b95Mathias Agopian        // however, if dpy and sur are null it means we're turning the
1859e37a11c21bcac1fbcac995cd34884eac37492b95Mathias Agopian        // screen off. no shall not call eglSwapBuffers() in that case.
1860ee0725d529a6adced20dd0182f9fd470607ce495Lajos Molnar
1861ee0725d529a6adced20dd0182f9fd470607ce495Lajos Molnar        if (hwc_dev->use_sgx) {
1862ee0725d529a6adced20dd0182f9fd470607ce495Lajos Molnar            if (!eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur)) {
186346de639b23db99d7b99ff1c676ac98b84b6336c6Steve Block                ALOGE("eglSwapBuffers error");
1864ee0725d529a6adced20dd0182f9fd470607ce495Lajos Molnar                err = HWC_EGL_ERROR;
1865ee0725d529a6adced20dd0182f9fd470607ce495Lajos Molnar                goto err_out;
1866ee0725d529a6adced20dd0182f9fd470607ce495Lajos Molnar            }
1867c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
1868c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
1869ee0725d529a6adced20dd0182f9fd470607ce495Lajos Molnar        //dump_dsscomp(dsscomp);
1870c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
187102150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian        // signal the event thread that a post has happened
1872751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        wakeup_hdmi_thread(hwc_dev);
187302150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian        if (hwc_dev->force_sgx > 0)
187402150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian            hwc_dev->force_sgx--;
187502150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian
1876876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        hwc_dev->comp_data.blit_data.rgz_flags = hwc_dev->blit_flags;
1877876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        hwc_dev->comp_data.blit_data.rgz_items = hwc_dev->blit_num;
1878876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        int omaplfb_comp_data_sz = sizeof(hwc_dev->comp_data) +
1879876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            (hwc_dev->comp_data.blit_data.rgz_items * sizeof(struct rgz_blt_entry));
1880876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1881876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1882876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        unsigned int nbufs = hwc_dev->post2_layers;
1883876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        if (hwc_dev->post2_blit_buffers) {
1884876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            /*
1885876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen             * We don't want to pass a NULL entry in the Post2, but we need to
1886876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen             * fix up buffer handle array and overlay indexes to account for
1887876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen             * this
1888876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen             */
1889876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            nbufs += hwc_dev->post2_blit_buffers - 1;
1890876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1891876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            if (hwc_dev->post2_layers > 1) {
1892876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                unsigned int i, j;
1893876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                for (i = 0; i < nbufs; i++) {
1894876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                    hwc_dev->buffers[i] = hwc_dev->buffers[i+1];
1895876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                }
1896876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                for (i = 1, j= 1; j < hwc_dev->post2_layers; i++, j++) {
1897876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                    dsscomp->ovls[j].ba = i;
1898876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                }
1899876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            }
1900876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        }
1901876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        ALOGI_IF(debugblt && hwc_dev->blt_policy != BLTPOLICY_DISABLED,
1902876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            "Post2, blits %d, ovl_buffers %d, blit_buffers %d sgx %d",
1903876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            hwc_dev->blit_num, hwc_dev->post2_layers, hwc_dev->post2_blit_buffers,
1904876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            hwc_dev->use_sgx);
1905876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1906876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        debug_post2(hwc_dev, nbufs);
1907ee0725d529a6adced20dd0182f9fd470607ce495Lajos Molnar        err = hwc_dev->fb_dev->Post2((framebuffer_device_t *)hwc_dev->fb_dev,
1908c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                                 hwc_dev->buffers,
1909876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                                 nbufs,
1910876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                                 dsscomp, omaplfb_comp_data_sz);
1911876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen#if 0
1912876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        if (!hwc_dev->use_sgx) {
1913876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            __u32 crt = 0;
1914876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            int err2 = ioctl(hwc_dev->fb_fd, FBIO_WAITFORVSYNC, &crt);
1915876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            if (err2) {
1916876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                ALOGE("failed to wait for vsync (%d)", errno);
1917876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                err = err ? : -errno;
1918876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            }
1919876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        }
1920876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen#endif
19217f2cbf97908a26e0b463d4fa20040b129216f86eLajos Molnar    }
192278fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    hwc_dev->last_ext_ovls = hwc_dev->ext_ovls;
192378fce72baff38f488a0117591d4241d278a48b1bLajos Molnar    hwc_dev->last_int_ovls = hwc_dev->post2_layers;
1924c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if (err)
192546de639b23db99d7b99ff1c676ac98b84b6336c6Steve Block        ALOGE("Post2 error");
1926c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
19276ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden    check_sync_fds(numDisplays, displays);
19286ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden
1929c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malcheverr_out:
19302125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    pthread_mutex_unlock(&hwc_dev->lock);
1931bd0fe036293115c9f9b182ed2a911bdd557ea491Lajos Molnar
1932876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (invalidate && hwc_dev->procs && hwc_dev->procs->invalidate)
1933bd0fe036293115c9f9b182ed2a911bdd557ea491Lajos Molnar        hwc_dev->procs->invalidate(hwc_dev->procs);
1934bd0fe036293115c9f9b182ed2a911bdd557ea491Lajos Molnar
1935c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    return err;
1936c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
1937c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
19386ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFaddenstatic void omap4_hwc_dump(struct hwc_composer_device_1 *dev, char *buff, int buff_len)
1939c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
1940c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev;
1941876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->comp_data.dsscomp_data;
1942734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    struct dump_buf log = {
1943734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        .buf = buff,
1944734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        .buf_len = buff_len,
1945734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    };
1946c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    int i;
1947c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
1948734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    dump_printf(&log, "omap4_hwc %d:\n", dsscomp->num_ovls);
1949734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar    dump_printf(&log, "  idle timeout: %dms\n", hwc_dev->idle);
1950c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
1951c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    for (i = 0; i < dsscomp->num_ovls; i++) {
1952c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        struct dss2_ovl_cfg *cfg = &dsscomp->ovls[i].cfg;
1953c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
1954734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        dump_printf(&log, "  layer %d:\n", i);
1955734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        dump_printf(&log, "     enabled: %s\n",
1956c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                          cfg->enabled ? "true" : "false");
1957734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        dump_printf(&log, "     buff: %p %dx%d stride: %d\n",
1958f1e357b2cf26fa5a50789061e068e4f0bd4ea772Mathias Agopian                          hwc_dev->buffers[i], cfg->width, cfg->height, cfg->stride);
1959734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        dump_printf(&log, "     src: (%d,%d) %dx%d\n",
1960c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                          cfg->crop.x, cfg->crop.y, cfg->crop.w, cfg->crop.h);
1961734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        dump_printf(&log, "     dst: (%d,%d) %dx%d\n",
1962c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                          cfg->win.x, cfg->win.y, cfg->win.w, cfg->win.h);
1963734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        dump_printf(&log, "     ix: %d\n", cfg->ix);
1964734de7a7631e5f115ee89c5b2f35c7c484098779Lajos Molnar        dump_printf(&log, "     zorder: %d\n\n", cfg->zorder);
1965c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    }
1966876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
1967876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (hwc_dev->blt_policy != BLTPOLICY_DISABLED) {
1968876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        dump_printf(&log, "  bltpolicy: %s, bltmode: %s\n",
1969876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            hwc_dev->blt_policy == BLTPOLICY_DEFAULT ? "default" :
1970876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                hwc_dev->blt_policy == BLTPOLICY_ALL ? "all" : "unknown",
1971876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                    hwc_dev->blt_mode == BLTMODE_PAINT ? "paint" : "regionize");
1972876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    }
1973876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    dump_printf(&log, "\n");
1974c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
1975c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
19760aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnarstatic void free_png_image(omap4_hwc_device_t *hwc_dev, struct omap4_hwc_img *img)
19770aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar{
19780aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    memset(img, 0, sizeof(*img));
19790aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar}
19800aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar
19810aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnarstatic int load_png_image(omap4_hwc_device_t *hwc_dev, char *path, struct omap4_hwc_img *img)
19820aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar{
19830aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    void *ptr = NULL;
19840aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    png_bytepp row_pointers = NULL;
19850aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar
19860aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    FILE *fd = fopen(path, "rb");
19870aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    if (!fd) {
198846de639b23db99d7b99ff1c676ac98b84b6336c6Steve Block        ALOGE("failed to open PNG file %s: (%d)", path, errno);
19890aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        return -EINVAL;
19900aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    }
19910aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar
19920aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    const int SIZE_PNG_HEADER = 8;
19930aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    __u8 header[SIZE_PNG_HEADER];
19940aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    fread(header, 1, SIZE_PNG_HEADER, fd);
19950aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    if (png_sig_cmp(header, 0, SIZE_PNG_HEADER)) {
199646de639b23db99d7b99ff1c676ac98b84b6336c6Steve Block        ALOGE("%s is not a PNG file", path);
19970aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        goto fail;
19980aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    }
19990aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar
20000aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
20010aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    if (!png_ptr)
20020aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar         goto fail_alloc;
20030aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    png_infop info_ptr = png_create_info_struct(png_ptr);
20040aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    if (!info_ptr)
20050aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar         goto fail_alloc;
20060aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar
20070aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    if (setjmp(png_jmpbuf(png_ptr)))
20080aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        goto fail_alloc;
20090aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar
20100aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    png_init_io(png_ptr, fd);
20110aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    png_set_sig_bytes(png_ptr, SIZE_PNG_HEADER);
20120aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    png_set_user_limits(png_ptr, limits.max_width, limits.max_height);
20130aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    png_read_info(png_ptr, info_ptr);
20140aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar
20150aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    __u8 bit_depth = png_get_bit_depth(png_ptr, info_ptr);
20160aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    __u32 width = png_get_image_width(png_ptr, info_ptr);
20170aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    __u32 height = png_get_image_height(png_ptr, info_ptr);
20180aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    __u8 color_type = png_get_color_type(png_ptr, info_ptr);
20190aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar
20200aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    switch (color_type) {
20210aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    case PNG_COLOR_TYPE_PALETTE:
20220aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        png_set_palette_to_rgb(png_ptr);
20230aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        png_set_filler(png_ptr, 128, PNG_FILLER_AFTER);
20240aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        break;
20250aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    case PNG_COLOR_TYPE_GRAY:
20260aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        if (bit_depth < 8) {
20270aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar            png_set_expand_gray_1_2_4_to_8(png_ptr);
20280aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar            if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
20290aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar                png_set_tRNS_to_alpha(png_ptr);
20300aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        } else {
20310aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar            png_set_filler(png_ptr, 128, PNG_FILLER_AFTER);
20320aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        }
20330aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        /* fall through */
20340aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    case PNG_COLOR_TYPE_GRAY_ALPHA:
20350aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        png_set_gray_to_rgb(png_ptr);
20360aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        break;
20370aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    case PNG_COLOR_TYPE_RGB:
20380aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        png_set_filler(png_ptr, 128, PNG_FILLER_AFTER);
20390aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        /* fall through */
20400aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    case PNG_COLOR_TYPE_RGB_ALPHA:
20410aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        png_set_bgr(png_ptr);
20420aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        break;
20430aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    default:
204446de639b23db99d7b99ff1c676ac98b84b6336c6Steve Block        ALOGE("unsupported PNG color: %x", color_type);
20450aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        goto fail_alloc;
20460aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    }
20470aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar
20480aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    if (bit_depth == 16)
20490aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        png_set_strip_16(png_ptr);
20500aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar
20510aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    const int bpp = 4;
20520aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    img->size = ALIGN(width * height * bpp, 4096);
20530aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    if (img->size > hwc_dev->img_mem_size) {
205446de639b23db99d7b99ff1c676ac98b84b6336c6Steve Block        ALOGE("image does not fit into framebuffer area (%d > %d)", img->size, hwc_dev->img_mem_size);
20550aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        goto fail_alloc;
20560aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    }
20570aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    img->ptr = hwc_dev->img_mem_ptr;
20580aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar
20590aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    row_pointers = calloc(height, sizeof(*row_pointers));
20600aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    if (!row_pointers) {
206146de639b23db99d7b99ff1c676ac98b84b6336c6Steve Block        ALOGE("failed to allocate row pointers");
20620aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        goto fail_alloc;
20630aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    }
20640aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    __u32 i;
20650aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    for (i = 0; i < height; i++)
20660aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        row_pointers[i] = img->ptr + i * width * bpp;
20670aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    png_set_rows(png_ptr, info_ptr, row_pointers);
20680aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    png_read_update_info(png_ptr, info_ptr);
20690aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    img->rowbytes = png_get_rowbytes(png_ptr, info_ptr);
20700aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar
20710aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    png_read_image(png_ptr, row_pointers);
20720aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    png_read_end(png_ptr, NULL);
20730aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    free(row_pointers);
20740aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
20750aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    fclose(fd);
20760aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    img->width = width;
20770aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    img->height = height;
20780aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    return 0;
20790aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar
20800aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnarfail_alloc:
20810aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    free_png_image(hwc_dev, img);
20820aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    free(row_pointers);
20830aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    if (!png_ptr || !info_ptr)
208446de639b23db99d7b99ff1c676ac98b84b6336c6Steve Block        ALOGE("failed to allocate PNG structures");
20850aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
20860aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnarfail:
20870aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    fclose(fd);
20880aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    return -EINVAL;
20890aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar}
20900aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar
2091c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2092c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic int omap4_hwc_device_close(hw_device_t* device)
2093c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
2094c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) device;;
2095c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
20962125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    if (hwc_dev) {
20972125fa148686edfa389121f946377aedaa3d9483Lajos Molnar        if (hwc_dev->dsscomp_fd >= 0)
20982125fa148686edfa389121f946377aedaa3d9483Lajos Molnar            close(hwc_dev->dsscomp_fd);
20992125fa148686edfa389121f946377aedaa3d9483Lajos Molnar        if (hwc_dev->hdmi_fb_fd >= 0)
21002125fa148686edfa389121f946377aedaa3d9483Lajos Molnar            close(hwc_dev->hdmi_fb_fd);
21017f2cbf97908a26e0b463d4fa20040b129216f86eLajos Molnar        if (hwc_dev->fb_fd >= 0)
21027f2cbf97908a26e0b463d4fa20040b129216f86eLajos Molnar            close(hwc_dev->fb_fd);
21032125fa148686edfa389121f946377aedaa3d9483Lajos Molnar        /* pthread will get killed when parent process exits */
21042125fa148686edfa389121f946377aedaa3d9483Lajos Molnar        pthread_mutex_destroy(&hwc_dev->lock);
2105751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        pthread_mutex_destroy(&hwc_dev->vsync_lock);
2106c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        free(hwc_dev);
21072125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    }
2108c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2109c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    return 0;
2110c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
2111c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2112c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic int omap4_hwc_open_fb_hal(IMG_framebuffer_device_public_t **fb_dev)
2113c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
2114e055e4bf77e6c429d7a159e8e853974d9dfc57adLajos Molnar    const struct hw_module_t *psModule;
2115c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    IMG_gralloc_module_public_t *psGrallocModule;
2116c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    int err;
2117c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2118e055e4bf77e6c429d7a159e8e853974d9dfc57adLajos Molnar    err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &psModule);
2119e055e4bf77e6c429d7a159e8e853974d9dfc57adLajos Molnar    psGrallocModule = (IMG_gralloc_module_public_t *) psModule;
2120e055e4bf77e6c429d7a159e8e853974d9dfc57adLajos Molnar
2121c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if(err)
2122c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        goto err_out;
2123c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2124b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar    if (strcmp(psGrallocModule->base.common.author, "Imagination Technologies")) {
2125c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        err = -EINVAL;
2126c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        goto err_out;
2127c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    }
2128c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2129c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    *fb_dev = psGrallocModule->psFrameBufferDevice;
2130c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2131c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    return 0;
2132c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2133c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malcheverr_out:
213446de639b23db99d7b99ff1c676ac98b84b6336c6Steve Block    ALOGE("Composer HAL failed to load compatible Graphics HAL");
2135c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    return err;
2136c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
21375db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket
2138876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chenstatic void set_primary_display_transform_matrix(omap4_hwc_device_t *hwc_dev)
2139876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen{
2140876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    /* create primary display translation matrix */
21415db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket    hwc_dev->fb_dis.ix = 0;/*Default display*/
2142c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2143876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    int ret = ioctl(hwc_dev->dsscomp_fd, DSSCIOC_QUERY_DISPLAY, &hwc_dev->fb_dis);
2144876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (ret)
2145876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        ALOGE("failed to get display info (%d): %m", errno);
2146876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
2147876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    int lcd_w = hwc_dev->fb_dis.timings.x_res;
2148876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    int lcd_h = hwc_dev->fb_dis.timings.y_res;
2149876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    int orig_w = hwc_dev->fb_dev->base.width;
2150876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    int orig_h = hwc_dev->fb_dev->base.height;
2151876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    hwc_rect_t region = {.left = 0, .top = 0, .right = orig_w, .bottom = orig_h};
2152876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    hwc_dev->primary_region = region;
2153876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    hwc_dev->primary_rotation = ((lcd_w > lcd_h) ^ (orig_w > orig_h)) ? 1 : 0;
2154876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    hwc_dev->primary_transform = ((lcd_w != orig_w)||(lcd_h != orig_h)) ? 1 : 0;
2155876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
2156876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    ALOGI("transforming FB (%dx%d) => (%dx%d) rot%d", orig_w, orig_h, lcd_w, lcd_h, hwc_dev->primary_rotation);
2157876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
2158876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    /* reorientation matrix is:
2159876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen       m = (center-from-target-center) * (scale-to-target) * (mirror) * (rotate) * (center-to-original-center) */
2160876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
2161876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    memcpy(hwc_dev->primary_m, m_unit, sizeof(m_unit));
2162876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    m_translate(hwc_dev->primary_m, -(orig_w >> 1), -(orig_h >> 1));
2163876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    m_rotate(hwc_dev->primary_m, hwc_dev->primary_rotation);
2164876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (hwc_dev->primary_rotation & 1)
2165876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen         swap(orig_w, orig_h);
2166876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    m_scale(hwc_dev->primary_m, orig_w, lcd_w, orig_h, lcd_h);
2167876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    m_translate(hwc_dev->primary_m, lcd_w >> 1, lcd_h >> 1);
21685db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket}
2169751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2170876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
21712b86fd0cbeb42123fc20b1f646ee81299e831d16Lajos Molnarstatic void handle_hotplug(omap4_hwc_device_t *hwc_dev)
21722125fa148686edfa389121f946377aedaa3d9483Lajos Molnar{
2173ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    omap4_hwc_ext_t *ext = &hwc_dev->ext;
21742b86fd0cbeb42123fc20b1f646ee81299e831d16Lajos Molnar    __u8 state = ext->hdmi_state;
2175876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
21765db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket    /* Ignore external HDMI logic if the primary display is HDMI */
21775db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket    if (hwc_dev->on_tv) {
21785db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket        ALOGI("Primary display is HDMI - skip clone/dock logic");
21795db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket
21805db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket        if (state) {
2181876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            __u32 xres = hwc_dev->fb_dev->base.width;
2182876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            __u32 yres = hwc_dev->fb_dev->base.height;
21835db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket            if (omap4_hwc_set_best_hdmi_mode(hwc_dev, xres, yres, ext->lcd_xpy)) {
2184876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                ALOGE("Failed to set HDMI mode");
21855db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket            }
2186876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            set_primary_display_transform_matrix(hwc_dev);
2187876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
21885db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket            ioctl(hwc_dev->fb_fd, FBIOBLANK, FB_BLANK_UNBLANK);
21895db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket
21905db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket            if (hwc_dev->procs && hwc_dev->procs->invalidate) {
21915db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket                hwc_dev->procs->invalidate(hwc_dev->procs);
21925db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket            }
2193876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        } else
21945db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket            ext->last_mode = 0;
21955db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket
21965db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket        return;
21975db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket    }
2198ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar
21992125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    pthread_mutex_lock(&hwc_dev->lock);
2200ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar    ext->dock.enabled = ext->mirror.enabled = 0;
22012125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    if (state) {
220241bb71e35280943ebe07ecfe1cf9e015918164e8Lajos Molnar        /* check whether we can clone and/or dock */
220341bb71e35280943ebe07ecfe1cf9e015918164e8Lajos Molnar        char value[PROPERTY_VALUE_MAX];
2204aa9be8a14744cae50a8f99e6cbb44be0d0c2c938Erik Gilling        property_get("persist.hwc.docking.enabled", value, "1");
2205ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar        ext->dock.enabled = atoi(value) > 0;
2206aa9be8a14744cae50a8f99e6cbb44be0d0c2c938Erik Gilling        property_get("persist.hwc.mirroring.enabled", value, "1");
2207ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar        ext->mirror.enabled = atoi(value) > 0;
22084e635e537afaa9f1416fa5bdbfd1b03afd8b7e6aLajos Molnar        property_get("persist.hwc.avoid_mode_change", value, "1");
22094e635e537afaa9f1416fa5bdbfd1b03afd8b7e6aLajos Molnar        ext->avoid_mode_change = atoi(value) > 0;
221041bb71e35280943ebe07ecfe1cf9e015918164e8Lajos Molnar
221141bb71e35280943ebe07ecfe1cf9e015918164e8Lajos Molnar        /* get cloning transformation */
2212aa9be8a14744cae50a8f99e6cbb44be0d0c2c938Erik Gilling        property_get("persist.hwc.docking.transform", value, "0");
2213ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar        ext->dock.rotation = atoi(value) & EXT_ROTATION;
2214ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar        ext->dock.hflip = (atoi(value) & EXT_HFLIP) > 0;
2215ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar        ext->dock.docking = 1;
22165db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket        property_get("persist.hwc.mirroring.transform", value, hwc_dev->fb_dis.timings.y_res > hwc_dev->fb_dis.timings.x_res ? "3" : "0");
2217ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar        ext->mirror.rotation = atoi(value) & EXT_ROTATION;
2218ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar        ext->mirror.hflip = (atoi(value) & EXT_HFLIP) > 0;
2219ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar        ext->mirror.docking = 0;
2220ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar
22212b86fd0cbeb42123fc20b1f646ee81299e831d16Lajos Molnar        if (ext->force_dock) {
22222b86fd0cbeb42123fc20b1f646ee81299e831d16Lajos Molnar            /* restrict to docking with no transform */
22232b86fd0cbeb42123fc20b1f646ee81299e831d16Lajos Molnar            ext->mirror.enabled = 0;
22242b86fd0cbeb42123fc20b1f646ee81299e831d16Lajos Molnar            ext->dock.rotation = 0;
22252b86fd0cbeb42123fc20b1f646ee81299e831d16Lajos Molnar            ext->dock.hflip = 0;
22260aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar
22270aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar            if (!dock_image.rowbytes) {
22280aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar                property_get("persist.hwc.dock_image", value, "/vendor/res/images/dock/dock.png");
22290aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar                load_png_image(hwc_dev, value, &dock_image);
22300aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar            }
22312b86fd0cbeb42123fc20b1f646ee81299e831d16Lajos Molnar        }
22322b86fd0cbeb42123fc20b1f646ee81299e831d16Lajos Molnar
2233ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar        /* select best mode for mirroring */
2234ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar        if (ext->mirror.enabled) {
22353837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar            ext->current = ext->mirror;
22363797fa989f5fee97caea2bbadf433a5a9ac03d8dLajos Molnar            ext->mirror_mode = 0;
22373837de4ff6b7562965758dd2a7af5550af1bd869Lajos Molnar            if (setup_mirroring(hwc_dev) == 0) {
22384e635e537afaa9f1416fa5bdbfd1b03afd8b7e6aLajos Molnar                ext->mirror_mode = ext->last_mode;
2239ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar                ioctl(hwc_dev->hdmi_fb_fd, FBIOBLANK, FB_BLANK_UNBLANK);
22404e635e537afaa9f1416fa5bdbfd1b03afd8b7e6aLajos Molnar            } else
2241ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar                ext->mirror.enabled = 0;
2242ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar        }
22434cb51e55fa79a592d50d94c0700660e42c988a0bLajos Molnar    } else {
22444cb51e55fa79a592d50d94c0700660e42c988a0bLajos Molnar        ext->last_mode = 0;
22452125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    }
2246bb0a9edbe9d4072ed227550d898f0c2d0149e0baSteve Block    ALOGI("external display changed (state=%d, mirror={%s tform=%ddeg%s}, dock={%s tform=%ddeg%s%s}, tv=%d", state,
2247ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar         ext->mirror.enabled ? "enabled" : "disabled",
2248ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar         ext->mirror.rotation * 90,
2249ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar         ext->mirror.hflip ? "+hflip" : "",
2250ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar         ext->dock.enabled ? "enabled" : "disabled",
2251ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar         ext->dock.rotation * 90,
2252ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar         ext->dock.hflip ? "+hflip" : "",
22532b86fd0cbeb42123fc20b1f646ee81299e831d16Lajos Molnar         ext->force_dock ? " forced" : "",
2254ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar         ext->on_tv);
2255ffa0d75e7fa7142eb289ccc9c7dc04e4cedb7c46Lajos Molnar
2256bd0fe036293115c9f9b182ed2a911bdd557ea491Lajos Molnar    pthread_mutex_unlock(&hwc_dev->lock);
2257834b8ba01376239a2f286a3766c14bdeeb166498Lajos Molnar
22583a96e09f206327fb5fd64d3fdc7ba3a315421082Jesse Hall    /* hwc_dev->procs is set right after the device is opened, but there is
22593a96e09f206327fb5fd64d3fdc7ba3a315421082Jesse Hall     * still a race condition where a hotplug event might occur after the open
22603a96e09f206327fb5fd64d3fdc7ba3a315421082Jesse Hall     * but before the procs are registered. */
2261876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (hwc_dev->procs && hwc_dev->procs->invalidate)
2262876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            hwc_dev->procs->invalidate(hwc_dev->procs);
22632125fa148686edfa389121f946377aedaa3d9483Lajos Molnar}
22642125fa148686edfa389121f946377aedaa3d9483Lajos Molnar
2265e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopianstatic void handle_uevents(omap4_hwc_device_t *hwc_dev, const char *buff, int len)
22662125fa148686edfa389121f946377aedaa3d9483Lajos Molnar{
2267e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    int dock;
2268e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    int hdmi;
2269e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    int vsync;
2270e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    int state = 0;
2271e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    uint64_t timestamp = 0;
2272e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    const char *s = buff;
2273e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian
2274e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    dock = !strcmp(s, "change@/devices/virtual/switch/dock");
2275e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    hdmi = !strcmp(s, "change@/devices/virtual/switch/hdmi");
2276bc85c3e357438aca809270bc8e85f5479bbe6a40Erik Gilling    vsync = !strcmp(s, "change@/devices/platform/omapfb") ||
2277bc85c3e357438aca809270bc8e85f5479bbe6a40Erik Gilling        !strcmp(s, "change@/devices/virtual/switch/omapfb-vsync");
2278e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian
2279e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    if (!dock && !vsync && !hdmi)
2280e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian       return;
22812125fa148686edfa389121f946377aedaa3d9483Lajos Molnar
22822125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    s += strlen(s) + 1;
22832125fa148686edfa389121f946377aedaa3d9483Lajos Molnar
22842125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    while(*s) {
2285e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian        if (!strncmp(s, "SWITCH_STATE=", strlen("SWITCH_STATE=")))
2286e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian            state = atoi(s + strlen("SWITCH_STATE="));
2287e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian        else if (!strncmp(s, "SWITCH_TIME=", strlen("SWITCH_TIME=")))
2288e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian            timestamp = strtoull(s + strlen("SWITCH_TIME="), NULL, 0);
2289bc85c3e357438aca809270bc8e85f5479bbe6a40Erik Gilling        else if (!strncmp(s, "VSYNC=", strlen("VSYNC=")))
2290bc85c3e357438aca809270bc8e85f5479bbe6a40Erik Gilling            timestamp = strtoull(s + strlen("VSYNC="), NULL, 0);
22912125fa148686edfa389121f946377aedaa3d9483Lajos Molnar
22922125fa148686edfa389121f946377aedaa3d9483Lajos Molnar        s += strlen(s) + 1;
2293e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian        if (s - buff >= len)
2294e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian            break;
2295e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    }
2296e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian
2297e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    if (vsync) {
2298751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        fire_vsync_event(hwc_dev, timestamp);
2299e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    } else {
2300751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        if (dock) {
2301e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian            hwc_dev->ext.force_dock = state == 1;
2302751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        } else {
2303751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            /* If the primary display is HDMI, VSYNC is enabled, and HDMI's plug
2304751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen             * state has just gone from 1->0, then we need to be sure to start
2305751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen             * faking the VSYNC events.
2306751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen             */
2307751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            if (hwc_dev->on_tv) {
2308751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                int new_state, state_change;
2309751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2310751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                pthread_mutex_lock(&hwc_dev->vsync_lock);
2311751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2312751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                new_state = state == 1;
2313751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                state_change = (new_state != hwc_dev->ext.hdmi_state);
2314751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                hwc_dev->ext.hdmi_state = new_state;
2315751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                if (state_change && !new_state)
2316751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                    wakeup_hdmi_thread(hwc_dev);
2317751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2318751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                pthread_mutex_unlock(&hwc_dev->vsync_lock);
2319751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            } else {
2320751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                hwc_dev->ext.hdmi_state = state == 1;
2321751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            }
2322751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        }
2323e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian        handle_hotplug(hwc_dev);
23242125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    }
23252125fa148686edfa389121f946377aedaa3d9483Lajos Molnar}
23262125fa148686edfa389121f946377aedaa3d9483Lajos Molnar
23272125fa148686edfa389121f946377aedaa3d9483Lajos Molnarstatic void *omap4_hwc_hdmi_thread(void *data)
23282125fa148686edfa389121f946377aedaa3d9483Lajos Molnar{
23292125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    omap4_hwc_device_t *hwc_dev = data;
23302125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    static char uevent_desc[4096];
233102150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian    struct pollfd fds[2];
2332b1c5d8ef7fc96ef49a1eaef0d81ff35dc4d2e4e7Jamie Gennis    int invalidate = 0;
233302150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian    int timeout;
233402150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian    int err;
233502150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian
2336e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
2337e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian
23382125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    uevent_init();
23392125fa148686edfa389121f946377aedaa3d9483Lajos Molnar
234002150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian    fds[0].fd = uevent_get_fd();
234102150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian    fds[0].events = POLLIN;
2342751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    fds[1].fd = hwc_dev->wakeup_evt;
234302150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian    fds[1].events = POLLIN;
234402150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian
234502150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian    timeout = hwc_dev->idle ? hwc_dev->idle : -1;
234602150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian
23472125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    memset(uevent_desc, 0, sizeof(uevent_desc));
23482125fa148686edfa389121f946377aedaa3d9483Lajos Molnar
23492125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    do {
2350751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        uint64_t idle_wakeup  = (uint64_t)(-1);
2351751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        uint64_t vsync_wakeup = (uint64_t)(-1);
2352751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        uint64_t now = vsync_clock_now();
2353751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        uint64_t effective_wakeup;
2354751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        int effective_timeout;
2355751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2356751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        if (timeout >= 0)
2357751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            idle_wakeup = now + (((uint64_t)timeout) * 1000000);
2358751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2359751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        if (hwc_dev->on_tv) {
2360751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            pthread_mutex_lock(&hwc_dev->vsync_lock);
2361751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2362751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            if (!hwc_dev->ext.hdmi_state && hwc_dev->vsync_enabled) {
2363751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                vsync_wakeup = hwc_dev->last_vsync_time_valid
2364751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                             ? hwc_dev->last_vsync_time
2365751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                             : now;
2366751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2367751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                vsync_wakeup += hwc_dev->fake_vsync_period;
2368751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2369751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                if (vsync_wakeup < now)
2370751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                    vsync_wakeup = now;
2371751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            }
2372751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2373751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            pthread_mutex_unlock(&hwc_dev->vsync_lock);
2374751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        }
2375751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2376751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        effective_wakeup = idle_wakeup < vsync_wakeup
2377751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                         ? idle_wakeup
2378751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                         : vsync_wakeup;
2379751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        if (effective_wakeup == (uint64_t)(-1))
2380751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            effective_timeout = -1;
2381751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        else if (effective_wakeup <= now)
2382751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            effective_timeout = 0;
2383751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        else
2384751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            effective_timeout = (int)((effective_wakeup - now + 999999) / 1000000);
2385751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2386751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        if (effective_timeout)
2387751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            err = poll(fds, 2, effective_timeout);
2388751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        else
2389751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            err = 0;
2390751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2391751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        now = vsync_clock_now();
239202150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian
239302150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian        if (err == 0) {
2394751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            int fired = 0;
2395751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2396751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            if (now >= vsync_wakeup) {
2397751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                fire_vsync_event(hwc_dev, vsync_wakeup);
2398751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                fired = 1;
2399751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            }
2400751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2401751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            if (hwc_dev->idle && (now >= idle_wakeup)) {
24023a96e09f206327fb5fd64d3fdc7ba3a315421082Jesse Hall                if (hwc_dev->procs) {
2403b1c5d8ef7fc96ef49a1eaef0d81ff35dc4d2e4e7Jamie Gennis                    pthread_mutex_lock(&hwc_dev->lock);
2404b1c5d8ef7fc96ef49a1eaef0d81ff35dc4d2e4e7Jamie Gennis                    invalidate = !hwc_dev->force_sgx && hwc_dev->ovls_blending;
2405b1c5d8ef7fc96ef49a1eaef0d81ff35dc4d2e4e7Jamie Gennis                    if (invalidate) {
2406b1c5d8ef7fc96ef49a1eaef0d81ff35dc4d2e4e7Jamie Gennis                        hwc_dev->force_sgx = 2;
2407b1c5d8ef7fc96ef49a1eaef0d81ff35dc4d2e4e7Jamie Gennis                    }
2408b1c5d8ef7fc96ef49a1eaef0d81ff35dc4d2e4e7Jamie Gennis                    pthread_mutex_unlock(&hwc_dev->lock);
2409b1c5d8ef7fc96ef49a1eaef0d81ff35dc4d2e4e7Jamie Gennis
2410b1c5d8ef7fc96ef49a1eaef0d81ff35dc4d2e4e7Jamie Gennis                    if (invalidate) {
2411b1c5d8ef7fc96ef49a1eaef0d81ff35dc4d2e4e7Jamie Gennis                        hwc_dev->procs->invalidate(hwc_dev->procs);
2412b1c5d8ef7fc96ef49a1eaef0d81ff35dc4d2e4e7Jamie Gennis                        timeout = -1;
2413b1c5d8ef7fc96ef49a1eaef0d81ff35dc4d2e4e7Jamie Gennis                    }
241402150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian                }
241502150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian
2416751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                fired = 1;
241702150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian            }
2418751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2419751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            if (fired)
2420751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                continue;
242102150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian        }
242202150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian
242302150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian        if (err == -1) {
242402150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian            if (errno != EINTR)
242546de639b23db99d7b99ff1c676ac98b84b6336c6Steve Block                ALOGE("event error: %m");
242602150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian            continue;
242702150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian        }
242802150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian
2429751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        if (fds[1].revents & POLLIN) {
2430751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            uint64_t tmp;
2431751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2432751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            read(hwc_dev->wakeup_evt, &tmp, sizeof(tmp));
2433751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
243402150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian            if (!hwc_dev->force_sgx)
243502150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian                timeout = hwc_dev->idle ? hwc_dev->idle : -1;
243602150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian        }
243702150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian
243802150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian        if (fds[0].revents & POLLIN) {
243902150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian            /* keep last 2 zeroes to ensure double 0 termination */
2440e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian            int len = uevent_next_event(uevent_desc, sizeof(uevent_desc) - 2);
2441e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian            handle_uevents(hwc_dev, uevent_desc, len);
244202150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian        }
24432125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    } while (1);
24442125fa148686edfa389121f946377aedaa3d9483Lajos Molnar
24452125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    return NULL;
24462125fa148686edfa389121f946377aedaa3d9483Lajos Molnar}
24472125fa148686edfa389121f946377aedaa3d9483Lajos Molnar
24486ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFaddenstatic void omap4_hwc_registerProcs(struct hwc_composer_device_1* dev,
24492125fa148686edfa389121f946377aedaa3d9483Lajos Molnar                                    hwc_procs_t const* procs)
24502125fa148686edfa389121f946377aedaa3d9483Lajos Molnar{
2451b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar    omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) dev;
24522125fa148686edfa389121f946377aedaa3d9483Lajos Molnar
2453b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar    hwc_dev->procs = (typeof(hwc_dev->procs)) procs;
24542125fa148686edfa389121f946377aedaa3d9483Lajos Molnar}
24552125fa148686edfa389121f946377aedaa3d9483Lajos Molnar
24566ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFaddenstatic int omap4_hwc_query(struct hwc_composer_device_1* dev,
2457e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian        int what, int* value)
2458e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian{
2459e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) dev;
2460e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian
2461e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    switch (what) {
2462e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    case HWC_BACKGROUND_LAYER_SUPPORTED:
2463e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian        // we don't support the background layer yet
2464e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian        value[0] = 0;
2465e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian        break;
2466e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    case HWC_VSYNC_PERIOD:
2467e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian        // vsync period in nanosecond
2468e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian        value[0] = 1000000000.0 / hwc_dev->fb_dev->base.fps;
2469e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian        break;
2470e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    default:
2471e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian        // unsupported query
2472e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian        return -EINVAL;
2473e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    }
2474e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    return 0;
2475e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian}
2476e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian
24776ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFaddenstatic int omap4_hwc_event_control(struct hwc_composer_device_1* dev,
24786ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden        int dpy, int event, int enabled)
2479e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian{
2480e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) dev;
2481e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian
2482e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    switch (event) {
2483e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    case HWC_EVENT_VSYNC:
2484e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    {
2485e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian        int val = !!enabled;
2486e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian        int err;
2487e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian
2488751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        /* If the primary display is HDMI, then we need to be sure to fake a
2489751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen         * stream vsync events if vsync is enabled, but HDMI happens to be
2490751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen         * disconnected.
2491751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen         */
2492751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        if (hwc_dev->on_tv) {
2493751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            pthread_mutex_lock(&hwc_dev->vsync_lock);
2494751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2495751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            if (!val)
2496751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                hwc_dev->last_vsync_time_valid = 0;
2497751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2498751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            /* If VSYNC is enabled, but HDMI is not actually plugged in, we need
2499751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen             * to fake it.  Poke the work thread to make sure it is taking care
2500751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen             * of things.
2501751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen             */
2502751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            if (!hwc_dev->ext.hdmi_state && !hwc_dev->vsync_enabled && val)
2503751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen                wakeup_hdmi_thread(hwc_dev);
2504751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2505751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            hwc_dev->vsync_enabled = val;
2506751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2507751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            err = ioctl(hwc_dev->fb_fd, OMAPFB_ENABLEVSYNC, &val);
2508751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            pthread_mutex_unlock(&hwc_dev->vsync_lock);
2509751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        } else {
2510751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            err = ioctl(hwc_dev->fb_fd, OMAPFB_ENABLEVSYNC, &val);
2511751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        }
2512751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2513e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian        if (err < 0)
2514e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian            return -errno;
2515e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian
2516e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian        return 0;
2517e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    }
2518e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    default:
2519e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian        return -EINVAL;
2520e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    }
2521e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian}
2522e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian
25233a96e09f206327fb5fd64d3fdc7ba3a315421082Jesse Hallstatic int omap4_hwc_blank(struct hwc_composer_device_1 *dev, int dpy, int blank)
25246ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden{
25256ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden    // We're using an older method of screen blanking based on
25266ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden    // early_suspend in the kernel.  No need to do anything here.
25276ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden    return 0;
25286ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden}
25296ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden
2530c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic int omap4_hwc_device_open(const hw_module_t* module, const char* name,
2531c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                hw_device_t** device)
2532c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
2533c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    omap4_hwc_module_t *hwc_mod = (omap4_hwc_module_t *)module;
2534c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    omap4_hwc_device_t *hwc_dev;
25352125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    int err = 0;
2536c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2537c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
2538c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        return -EINVAL;
2539c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    }
2540c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2541c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if (!hwc_mod->fb_dev) {
2542c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        err = omap4_hwc_open_fb_hal(&hwc_mod->fb_dev);
2543c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        if (err)
2544c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            return err;
2545c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2546c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        if (!hwc_mod->fb_dev) {
254746de639b23db99d7b99ff1c676ac98b84b6336c6Steve Block            ALOGE("Framebuffer HAL not opened before HWC");
2548c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            return -EFAULT;
2549c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
2550c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        hwc_mod->fb_dev->bBypassPost = 1;
2551c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    }
2552c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2553c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    hwc_dev = (omap4_hwc_device_t *)malloc(sizeof(*hwc_dev));
2554c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if (hwc_dev == NULL)
2555c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        return -ENOMEM;
2556c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2557c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    memset(hwc_dev, 0, sizeof(*hwc_dev));
2558c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2559c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    hwc_dev->base.common.tag = HARDWARE_DEVICE_TAG;
25606ce89d3c3ec5d07a21bd1fc33f6ff61d67acbe95Andy McFadden    hwc_dev->base.common.version = HWC_DEVICE_API_VERSION_1_0;
2561c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    hwc_dev->base.common.module = (hw_module_t *)module;
2562c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    hwc_dev->base.common.close = omap4_hwc_device_close;
2563c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    hwc_dev->base.prepare = omap4_hwc_prepare;
2564c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    hwc_dev->base.set = omap4_hwc_set;
25653a96e09f206327fb5fd64d3fdc7ba3a315421082Jesse Hall    hwc_dev->base.eventControl = omap4_hwc_event_control;
25663a96e09f206327fb5fd64d3fdc7ba3a315421082Jesse Hall    hwc_dev->base.blank = omap4_hwc_blank;
2567e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian    hwc_dev->base.query = omap4_hwc_query;
25683a96e09f206327fb5fd64d3fdc7ba3a315421082Jesse Hall    hwc_dev->base.registerProcs = omap4_hwc_registerProcs;
25693a96e09f206327fb5fd64d3fdc7ba3a315421082Jesse Hall    hwc_dev->base.dump = omap4_hwc_dump;
2570c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    hwc_dev->fb_dev = hwc_mod->fb_dev;
2571751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    hwc_dev->wakeup_evt = -1;
2572c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    *device = &hwc_dev->base.common;
2573c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2574751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    hwc_dev->vsync_enabled = 0;
2575751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    hwc_dev->last_vsync_time_valid = 0;
2576751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    hwc_dev->fake_vsync_period = 1000000000ull/60;
2577751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
25782125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    hwc_dev->dsscomp_fd = open("/dev/dsscomp", O_RDWR);
25797f2cbf97908a26e0b463d4fa20040b129216f86eLajos Molnar    if (hwc_dev->dsscomp_fd < 0) {
258046de639b23db99d7b99ff1c676ac98b84b6336c6Steve Block        ALOGE("failed to open dsscomp (%d)", errno);
25817f2cbf97908a26e0b463d4fa20040b129216f86eLajos Molnar        err = -errno;
25827f2cbf97908a26e0b463d4fa20040b129216f86eLajos Molnar        goto done;
25837f2cbf97908a26e0b463d4fa20040b129216f86eLajos Molnar    }
25842125fa148686edfa389121f946377aedaa3d9483Lajos Molnar
2585876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    int ret = ioctl(hwc_dev->dsscomp_fd, DSSCIOC_QUERY_PLATFORM, &limits);
2586876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (ret) {
2587876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        ALOGE("failed to get platform limits (%d): %m", errno);
2588876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        err = -errno;
2589876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        goto done;
2590876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    }
2591876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
25927f2cbf97908a26e0b463d4fa20040b129216f86eLajos Molnar    hwc_dev->fb_fd = open("/dev/graphics/fb0", O_RDWR);
25937f2cbf97908a26e0b463d4fa20040b129216f86eLajos Molnar    if (hwc_dev->fb_fd < 0) {
259446de639b23db99d7b99ff1c676ac98b84b6336c6Steve Block        ALOGE("failed to open fb (%d)", errno);
25957f2cbf97908a26e0b463d4fa20040b129216f86eLajos Molnar        err = -errno;
25967f2cbf97908a26e0b463d4fa20040b129216f86eLajos Molnar        goto done;
25977f2cbf97908a26e0b463d4fa20040b129216f86eLajos Molnar    }
25982125fa148686edfa389121f946377aedaa3d9483Lajos Molnar
25990aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    struct fb_fix_screeninfo fix;
26000aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    if (ioctl(hwc_dev->fb_fd, FBIOGET_FSCREENINFO, &fix)) {
260146de639b23db99d7b99ff1c676ac98b84b6336c6Steve Block        ALOGE("failed to get fb info (%d)", errno);
26020aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        err = -errno;
26030aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        goto done;
26040aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    }
26050aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar
26060aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    hwc_dev->img_mem_size = fix.smem_len;
26070aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    hwc_dev->img_mem_ptr = mmap(NULL, fix.smem_len, PROT_WRITE, MAP_SHARED, hwc_dev->fb_fd, 0);
26080aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    if (hwc_dev->img_mem_ptr == MAP_FAILED) {
260946de639b23db99d7b99ff1c676ac98b84b6336c6Steve Block        ALOGE("failed to map fb memory");
26100aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        err = -errno;
26110aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar        goto done;
26120aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar    }
26130aead355133c2a087cb369c5eb62a07cbd4a13beLajos Molnar
2614876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    /* Allocate the maximum buffers that we can receive from HWC */
2615876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    hwc_dev->buffers = malloc(sizeof(buffer_handle_t) * MAX_HWC_LAYERS);
2616c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if (!hwc_dev->buffers) {
26172125fa148686edfa389121f946377aedaa3d9483Lajos Molnar        err = -ENOMEM;
26182125fa148686edfa389121f946377aedaa3d9483Lajos Molnar        goto done;
26192125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    }
26202125fa148686edfa389121f946377aedaa3d9483Lajos Molnar
2621876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    ret = ioctl(hwc_dev->dsscomp_fd, DSSCIOC_QUERY_DISPLAY, &hwc_dev->fb_dis);
2622d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar    if (ret) {
262346de639b23db99d7b99ff1c676ac98b84b6336c6Steve Block        ALOGE("failed to get display info (%d): %m", errno);
2624d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar        err = -errno;
2625d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar        goto done;
2626d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar    }
26273797fa989f5fee97caea2bbadf433a5a9ac03d8dLajos Molnar    hwc_dev->ext.lcd_xpy = (float) hwc_dev->fb_dis.width_in_mm / hwc_dev->fb_dis.timings.x_res /
26283797fa989f5fee97caea2bbadf433a5a9ac03d8dLajos Molnar                            hwc_dev->fb_dis.height_in_mm       * hwc_dev->fb_dis.timings.y_res;
2629d98920b36b52ca1784742cbd053c631ae62ca1c4Lajos Molnar
26306d94b7785c5318b6de36193a7f5488a88b6178ebDandawate Saket    if (hwc_dev->fb_dis.channel == OMAP_DSS_CHANNEL_DIGIT) {
26315db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket        ALOGI("Primary display is HDMI");
26325db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket        hwc_dev->on_tv = 1;
26335db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket    }
26346d94b7785c5318b6de36193a7f5488a88b6178ebDandawate Saket    else {
26355db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket        hwc_dev->hdmi_fb_fd = open("/dev/graphics/fb1", O_RDWR);
26365db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket        if (hwc_dev->hdmi_fb_fd < 0) {
26375db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket            ALOGE("failed to open hdmi fb (%d)", errno);
26385db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket            err = -errno;
26395db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket            goto done;
26405db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket        }
26415db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket    }
2642876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    set_primary_display_transform_matrix(hwc_dev);
26435db21d521ed41e2e2cc110b698981e841e027287Dandawate Saket
2644751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    if ((hwc_dev->wakeup_evt = eventfd(0, EFD_NONBLOCK)) < 0) {
2645751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            ALOGE("failed to eventfd (%d): %m", errno);
264602150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian            err = -errno;
264702150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian            goto done;
264802150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian    }
264902150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian
26502125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    if (pthread_mutex_init(&hwc_dev->lock, NULL)) {
265146de639b23db99d7b99ff1c676ac98b84b6336c6Steve Block        ALOGE("failed to create mutex (%d): %m", errno);
2652b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar        err = -errno;
2653b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar        goto done;
26542125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    }
2655751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2656751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    if (pthread_mutex_init(&hwc_dev->vsync_lock, NULL)) {
2657751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        ALOGE("failed to create vsync mutex (%d): %m", errno);
2658751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        err = -errno;
2659751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        goto done;
2660751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen    }
2661751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen
2662876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (pthread_create(&hwc_dev->hdmi_thread, NULL, omap4_hwc_hdmi_thread, hwc_dev))
2663876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    {
266446de639b23db99d7b99ff1c676ac98b84b6336c6Steve Block        ALOGE("failed to create HDMI listening thread (%d): %m", errno);
2665b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar        err = -errno;
2666b79b42d125e488c0bcf101edfd3b1f30bafae53eLajos Molnar        goto done;
2667c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    }
2668c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2669c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    /* get debug properties */
2670c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2671c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    /* see if hwc is enabled at all */
2672c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    char value[PROPERTY_VALUE_MAX];
2673c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    property_get("debug.hwc.rgb_order", value, "1");
2674c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    hwc_dev->flags_rgb_order = atoi(value);
2675c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    property_get("debug.hwc.nv12_only", value, "0");
2676c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    hwc_dev->flags_nv12_only = atoi(value);
267702150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian    property_get("debug.hwc.idle", value, "250");
267802150d77cba303ea6c532fa740910fbab5e3e1ccMathias Agopian    hwc_dev->idle = atoi(value);
26792125fa148686edfa389121f946377aedaa3d9483Lajos Molnar
26808d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    /* get the board specific clone properties */
26818d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    /* 0:0:1280:720 */
2682dd922b9387f70e24b3462afe1bdc86ceb7541d4bLajos Molnar    if (property_get("persist.hwc.mirroring.region", value, "") <= 0 ||
26838d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        sscanf(value, "%d:%d:%d:%d",
26848d546610cba3698c62af537d97e38a7368362f1aLajos Molnar               &hwc_dev->ext.mirror_region.left, &hwc_dev->ext.mirror_region.top,
26858d546610cba3698c62af537d97e38a7368362f1aLajos Molnar               &hwc_dev->ext.mirror_region.right, &hwc_dev->ext.mirror_region.bottom) != 4 ||
26868d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        hwc_dev->ext.mirror_region.left >= hwc_dev->ext.mirror_region.right ||
26878d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        hwc_dev->ext.mirror_region.top >= hwc_dev->ext.mirror_region.bottom) {
2688876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        struct hwc_rect fb_region = { .right = hwc_dev->fb_dev->base.width, .bottom = hwc_dev->fb_dev->base.height };
26898d546610cba3698c62af537d97e38a7368362f1aLajos Molnar        hwc_dev->ext.mirror_region = fb_region;
26908d546610cba3698c62af537d97e38a7368362f1aLajos Molnar    }
2691bb0a9edbe9d4072ed227550d898f0c2d0149e0baSteve Block    ALOGI("clone region is set to (%d,%d) to (%d,%d)",
26928d546610cba3698c62af537d97e38a7368362f1aLajos Molnar         hwc_dev->ext.mirror_region.left, hwc_dev->ext.mirror_region.top,
26938d546610cba3698c62af537d97e38a7368362f1aLajos Molnar         hwc_dev->ext.mirror_region.right, hwc_dev->ext.mirror_region.bottom);
26948d546610cba3698c62af537d97e38a7368362f1aLajos Molnar
26952125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    /* read switch state */
26962125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    int sw_fd = open("/sys/class/switch/hdmi/state", O_RDONLY);
26972125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    if (sw_fd >= 0) {
26982125fa148686edfa389121f946377aedaa3d9483Lajos Molnar        char value;
26992125fa148686edfa389121f946377aedaa3d9483Lajos Molnar        if (read(sw_fd, &value, 1) == 1)
27002b86fd0cbeb42123fc20b1f646ee81299e831d16Lajos Molnar            hwc_dev->ext.hdmi_state = value == '1';
27012b86fd0cbeb42123fc20b1f646ee81299e831d16Lajos Molnar        close(sw_fd);
27022b86fd0cbeb42123fc20b1f646ee81299e831d16Lajos Molnar    }
27032b86fd0cbeb42123fc20b1f646ee81299e831d16Lajos Molnar    sw_fd = open("/sys/class/switch/dock/state", O_RDONLY);
27042b86fd0cbeb42123fc20b1f646ee81299e831d16Lajos Molnar    if (sw_fd >= 0) {
27052b86fd0cbeb42123fc20b1f646ee81299e831d16Lajos Molnar        char value;
27062b86fd0cbeb42123fc20b1f646ee81299e831d16Lajos Molnar        if (read(sw_fd, &value, 1) == 1)
27072b86fd0cbeb42123fc20b1f646ee81299e831d16Lajos Molnar            hwc_dev->ext.force_dock = value == '1';
27082125fa148686edfa389121f946377aedaa3d9483Lajos Molnar        close(sw_fd);
27092125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    }
27102b86fd0cbeb42123fc20b1f646ee81299e831d16Lajos Molnar    handle_hotplug(hwc_dev);
27112125fa148686edfa389121f946377aedaa3d9483Lajos Molnar
2712bb0a9edbe9d4072ed227550d898f0c2d0149e0baSteve Block    ALOGI("omap4_hwc_device_open(rgb_order=%d nv12_only=%d)",
2713c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        hwc_dev->flags_rgb_order, hwc_dev->flags_nv12_only);
2714c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2715876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    int gc2d_fd = open("/dev/gcioctl", O_RDWR);
2716876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    if (gc2d_fd < 0) {
2717876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        ALOGI("Unable to open gc-core device (%d), blits disabled", errno);
2718876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        hwc_dev->blt_policy = BLTPOLICY_DISABLED;
2719876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    } else {
2720876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        property_get("persist.hwc.bltmode", value, "1");
2721876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        hwc_dev->blt_mode = atoi(value);
2722876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        property_get("persist.hwc.bltpolicy", value, "1");
2723876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        hwc_dev->blt_policy = atoi(value);
2724876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        ALOGI("blitter present, blits mode %d, blits policy %d", hwc_dev->blt_mode, hwc_dev->blt_policy);
2725876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        close(gc2d_fd);
2726876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
2727876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        if (rgz_get_screengeometry(hwc_dev->fb_fd, &gscrngeom,
2728876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen                hwc_dev->fb_dev->base.format) != 0) {
2729876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            err = -EINVAL;
2730876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen            goto done;
2731876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen        }
2732876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen    }
2733876331fc77f6763c8c390d1289ead00f89f8d9feMike J. Chen
27342125fa148686edfa389121f946377aedaa3d9483Lajos Molnardone:
27352125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    if (err && hwc_dev) {
27362125fa148686edfa389121f946377aedaa3d9483Lajos Molnar        if (hwc_dev->dsscomp_fd >= 0)
27372125fa148686edfa389121f946377aedaa3d9483Lajos Molnar            close(hwc_dev->dsscomp_fd);
27382125fa148686edfa389121f946377aedaa3d9483Lajos Molnar        if (hwc_dev->hdmi_fb_fd >= 0)
27392125fa148686edfa389121f946377aedaa3d9483Lajos Molnar            close(hwc_dev->hdmi_fb_fd);
27407f2cbf97908a26e0b463d4fa20040b129216f86eLajos Molnar        if (hwc_dev->fb_fd >= 0)
27417f2cbf97908a26e0b463d4fa20040b129216f86eLajos Molnar            close(hwc_dev->fb_fd);
2742751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        if (hwc_dev->wakeup_evt >= 0)
2743751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen            close(hwc_dev->wakeup_evt);
27442125fa148686edfa389121f946377aedaa3d9483Lajos Molnar        pthread_mutex_destroy(&hwc_dev->lock);
2745751880491cd2d46a6bb0ff1070a0dc05557aa041Mike J. Chen        pthread_mutex_destroy(&hwc_dev->vsync_lock);
27462125fa148686edfa389121f946377aedaa3d9483Lajos Molnar        free(hwc_dev->buffers);
27472125fa148686edfa389121f946377aedaa3d9483Lajos Molnar        free(hwc_dev);
27482125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    }
27492125fa148686edfa389121f946377aedaa3d9483Lajos Molnar
27502125fa148686edfa389121f946377aedaa3d9483Lajos Molnar    return err;
2751c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
2752c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2753c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic struct hw_module_methods_t omap4_hwc_module_methods = {
2754c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    .open = omap4_hwc_device_open,
2755c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev};
2756c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2757c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevomap4_hwc_module_t HAL_MODULE_INFO_SYM = {
2758c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    .base = {
2759c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        .common = {
2760c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            .tag =                  HARDWARE_MODULE_TAG,
2761e914b7e0a972af85845268ecf962773b8e4da977Mathias Agopian            .module_api_version =   HWC_MODULE_API_VERSION_0_1,
2762a35209b2e26289458670e04d6e62dee3d085ea63Mathias Agopian            .hal_api_version =      HARDWARE_HAL_API_VERSION,
2763c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            .id =                   HWC_HARDWARE_MODULE_ID,
2764c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            .name =                 "OMAP 44xx Hardware Composer HAL",
2765c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            .author =               "Texas Instruments",
2766c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            .methods =              &omap4_hwc_module_methods,
2767c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        },
2768c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    },
2769c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev};
2770