blob: d948f382a0816b305e60888a625d8512315ad158 [file] [log] [blame]
Greg Hackmann86eb1c62012-05-30 09:25:51 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <errno.h>
18#include <fcntl.h>
Greg Hackmann29724852012-07-23 15:31:10 -070019#include <poll.h>
Greg Hackmann86eb1c62012-05-30 09:25:51 -070020#include <pthread.h>
21#include <stdio.h>
22#include <stdlib.h>
23
24#include <sys/ioctl.h>
25#include <sys/mman.h>
26#include <sys/time.h>
27#include <sys/resource.h>
28
29#include <s3c-fb.h>
30
31#include <EGL/egl.h>
32
Erik Gilling87e707e2012-06-29 17:35:13 -070033#define HWC_REMOVE_DEPRECATED_VERSIONS 1
34
Greg Hackmann86eb1c62012-05-30 09:25:51 -070035#include <cutils/log.h>
36#include <hardware/gralloc.h>
37#include <hardware/hardware.h>
38#include <hardware/hwcomposer.h>
39#include <hardware_legacy/uevent.h>
40#include <utils/Vector.h>
41
Greg Hackmannf4cc0c32012-05-30 09:28:52 -070042#include <sync/sync.h>
43
Greg Hackmann86eb1c62012-05-30 09:25:51 -070044#include "ump.h"
45#include "ion.h"
46#include "gralloc_priv.h"
Benoit Gobycdd61b32012-07-09 12:09:59 -070047#include "exynos_gscaler.h"
Greg Hackmann86eb1c62012-05-30 09:25:51 -070048
Greg Hackmannf6f2e542012-07-16 16:10:27 -070049struct hwc_callback_entry {
50 void (*callback)(void *, private_handle_t *);
51 void *data;
Greg Hackmann86eb1c62012-05-30 09:25:51 -070052};
53typedef android::Vector<struct hwc_callback_entry> hwc_callback_queue_t;
54
Greg Hackmann31991d52012-07-13 13:23:11 -070055const size_t NUM_HW_WINDOWS = 5;
Greg Hackmann86eb1c62012-05-30 09:25:51 -070056const size_t NO_FB_NEEDED = NUM_HW_WINDOWS + 1;
Greg Hackmann31991d52012-07-13 13:23:11 -070057const size_t MAX_PIXELS = 2560 * 1600 * 2;
Greg Hackmann86eb1c62012-05-30 09:25:51 -070058
Erik Gilling87e707e2012-06-29 17:35:13 -070059struct exynos5_hwc_composer_device_1_t;
Greg Hackmann86eb1c62012-05-30 09:25:51 -070060
61struct exynos5_hwc_post_data_t {
Greg Hackmannf6f2e542012-07-16 16:10:27 -070062 exynos5_hwc_composer_device_1_t *pdev;
63 int overlay_map[NUM_HW_WINDOWS];
64 hwc_layer_1_t overlays[NUM_HW_WINDOWS];
65 int num_overlays;
66 size_t fb_window;
67 int fence;
68 pthread_mutex_t completion_lock;
69 pthread_cond_t completion;
Greg Hackmann86eb1c62012-05-30 09:25:51 -070070};
71
Erik Gilling87e707e2012-06-29 17:35:13 -070072struct exynos5_hwc_composer_device_1_t {
Greg Hackmannf6f2e542012-07-16 16:10:27 -070073 hwc_composer_device_1_t base;
Greg Hackmann86eb1c62012-05-30 09:25:51 -070074
Greg Hackmannf6f2e542012-07-16 16:10:27 -070075 int fd;
Greg Hackmann29724852012-07-23 15:31:10 -070076 int vsync_fd;
Greg Hackmannf6f2e542012-07-16 16:10:27 -070077 exynos5_hwc_post_data_t bufs;
Greg Hackmann86eb1c62012-05-30 09:25:51 -070078
Greg Hackmannf6f2e542012-07-16 16:10:27 -070079 const private_module_t *gralloc_module;
80 hwc_procs_t *procs;
81 pthread_t vsync_thread;
Benoit Gobycdd61b32012-07-09 12:09:59 -070082
Greg Hackmannf6f2e542012-07-16 16:10:27 -070083 bool hdmi_hpd;
84 bool hdmi_mirroring;
85 void *hdmi_gsc;
Greg Hackmann86eb1c62012-05-30 09:25:51 -070086};
87
Erik Gilling87e707e2012-06-29 17:35:13 -070088static void dump_layer(hwc_layer_1_t const *l)
Greg Hackmann86eb1c62012-05-30 09:25:51 -070089{
Greg Hackmannf6f2e542012-07-16 16:10:27 -070090 ALOGV("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, "
91 "{%d,%d,%d,%d}, {%d,%d,%d,%d}",
92 l->compositionType, l->flags, l->handle, l->transform,
93 l->blending,
94 l->sourceCrop.left,
95 l->sourceCrop.top,
96 l->sourceCrop.right,
97 l->sourceCrop.bottom,
98 l->displayFrame.left,
99 l->displayFrame.top,
100 l->displayFrame.right,
101 l->displayFrame.bottom);
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700102}
103
104static void dump_handle(private_handle_t *h)
105{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700106 ALOGV("\t\tformat = %d, width = %u, height = %u, bpp = %u, stride = %u",
107 h->format, h->width, h->height, h->bpp, h->stride);
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700108}
109
110static void dump_config(s3c_fb_win_config &c)
111{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700112 ALOGV("\tstate = %u", c.state);
113 if (c.state == c.S3C_FB_WIN_STATE_BUFFER) {
114 ALOGV("\t\tfd = %d, offset = %u, stride = %u, "
115 "x = %d, y = %d, w = %u, h = %u, "
116 "format = %u",
117 c.fd, c.offset, c.stride,
118 c.x, c.y, c.w, c.h,
119 c.format);
120 }
121 else if (c.state == c.S3C_FB_WIN_STATE_COLOR) {
122 ALOGV("\t\tcolor = %u", c.color);
123 }
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700124}
125
126inline int WIDTH(const hwc_rect &rect) { return rect.right - rect.left; }
127inline int HEIGHT(const hwc_rect &rect) { return rect.bottom - rect.top; }
Greg Hackmann31991d52012-07-13 13:23:11 -0700128template<typename T> inline T max(T a, T b) { return (a > b) ? a : b; }
129template<typename T> inline T min(T a, T b) { return (a < b) ? a : b; }
130
131static bool is_transformed(const hwc_layer_1_t &layer)
132{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700133 return layer.transform != 0;
Greg Hackmann31991d52012-07-13 13:23:11 -0700134}
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700135
Erik Gilling87e707e2012-06-29 17:35:13 -0700136static bool is_scaled(const hwc_layer_1_t &layer)
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700137{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700138 return WIDTH(layer.displayFrame) != WIDTH(layer.sourceCrop) ||
139 HEIGHT(layer.displayFrame) != HEIGHT(layer.sourceCrop);
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700140}
141
142static enum s3c_fb_pixel_format exynos5_format_to_s3c_format(int format)
143{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700144 switch (format) {
145 case HAL_PIXEL_FORMAT_RGBA_8888:
146 return S3C_FB_PIXEL_FORMAT_RGBA_8888;
147 case HAL_PIXEL_FORMAT_RGBX_8888:
148 return S3C_FB_PIXEL_FORMAT_RGBX_8888;
149 case HAL_PIXEL_FORMAT_RGBA_5551:
150 return S3C_FB_PIXEL_FORMAT_RGBA_5551;
151 case HAL_PIXEL_FORMAT_RGBA_4444:
152 return S3C_FB_PIXEL_FORMAT_RGBA_4444;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700153
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700154 default:
155 return S3C_FB_PIXEL_FORMAT_MAX;
156 }
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700157}
158
159static bool exynos5_format_is_supported(int format)
160{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700161 return exynos5_format_to_s3c_format(format) < S3C_FB_PIXEL_FORMAT_MAX;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700162}
163
164static bool exynos5_format_is_supported_by_gscaler(int format)
165{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700166 switch(format) {
167 case HAL_PIXEL_FORMAT_RGBA_8888:
168 case HAL_PIXEL_FORMAT_RGBX_8888:
169 case HAL_PIXEL_FORMAT_RGB_565:
170 case HAL_PIXEL_FORMAT_YV12:
171 return true;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700172
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700173 default:
174 return false;
175 }
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700176}
177
178static uint8_t exynos5_format_to_bpp(int format)
179{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700180 switch (format) {
181 case HAL_PIXEL_FORMAT_RGBA_8888:
182 case HAL_PIXEL_FORMAT_RGBX_8888:
183 return 32;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700184
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700185 case HAL_PIXEL_FORMAT_RGBA_5551:
186 case HAL_PIXEL_FORMAT_RGBA_4444:
187 return 16;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700188
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700189 default:
190 ALOGW("unrecognized pixel format %u", format);
191 return 0;
192 }
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700193}
194
Benoit Gobycdd61b32012-07-09 12:09:59 -0700195static int hdmi_enable(struct exynos5_hwc_composer_device_1_t *dev)
196{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700197 if (dev->hdmi_mirroring)
198 return 0;
Benoit Gobycdd61b32012-07-09 12:09:59 -0700199
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700200 exynos_gsc_img src_info;
201 exynos_gsc_img dst_info;
Benoit Gobycdd61b32012-07-09 12:09:59 -0700202
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700203 // TODO: Don't hardcode
204 int src_w = 2560;
205 int src_h = 1600;
206 int dst_w = 1920;
207 int dst_h = 1080;
Benoit Gobycdd61b32012-07-09 12:09:59 -0700208
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700209 dev->hdmi_gsc = exynos_gsc_create_exclusive(3, GSC_OUTPUT_MODE, GSC_OUT_TV);
210 if (!dev->hdmi_gsc) {
211 ALOGE("%s: exynos_gsc_create_exclusive failed", __func__);
212 return -ENODEV;
213 }
Benoit Gobycdd61b32012-07-09 12:09:59 -0700214
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700215 memset(&src_info, 0, sizeof(src_info));
216 memset(&dst_info, 0, sizeof(dst_info));
Benoit Gobycdd61b32012-07-09 12:09:59 -0700217
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700218 src_info.w = src_w;
219 src_info.h = src_h;
220 src_info.fw = src_w;
221 src_info.fh = src_h;
222 src_info.format = HAL_PIXEL_FORMAT_BGRA_8888;
Benoit Gobycdd61b32012-07-09 12:09:59 -0700223
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700224 dst_info.w = dst_w;
225 dst_info.h = dst_h;
226 dst_info.fw = dst_w;
227 dst_info.fh = dst_h;
228 dst_info.format = HAL_PIXEL_FORMAT_YV12;
Benoit Gobycdd61b32012-07-09 12:09:59 -0700229
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700230 int ret = exynos_gsc_config_exclusive(dev->hdmi_gsc, &src_info, &dst_info);
231 if (ret < 0) {
232 ALOGE("%s: exynos_gsc_config_exclusive failed %d", __func__, ret);
233 exynos_gsc_destroy(dev->hdmi_gsc);
234 dev->hdmi_gsc = NULL;
235 return ret;
236 }
Benoit Gobycdd61b32012-07-09 12:09:59 -0700237
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700238 dev->hdmi_mirroring = true;
239 return 0;
Benoit Gobycdd61b32012-07-09 12:09:59 -0700240}
241
242static void hdmi_disable(struct exynos5_hwc_composer_device_1_t *dev)
243{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700244 if (!dev->hdmi_mirroring)
245 return;
246 exynos_gsc_destroy(dev->hdmi_gsc);
247 dev->hdmi_gsc = NULL;
248 dev->hdmi_mirroring = false;
Benoit Gobycdd61b32012-07-09 12:09:59 -0700249}
250
251static int hdmi_output(struct exynos5_hwc_composer_device_1_t *dev, private_handle_t *fb)
252{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700253 exynos_gsc_img src_info;
254 exynos_gsc_img dst_info;
Benoit Gobycdd61b32012-07-09 12:09:59 -0700255
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700256 memset(&src_info, 0, sizeof(src_info));
257 memset(&dst_info, 0, sizeof(dst_info));
Benoit Gobycdd61b32012-07-09 12:09:59 -0700258
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700259 src_info.yaddr = fb->fd;
Benoit Gobycdd61b32012-07-09 12:09:59 -0700260
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700261 int ret = exynos_gsc_run_exclusive(dev->hdmi_gsc, &src_info, &dst_info);
262 if (ret < 0) {
263 ALOGE("%s: exynos_gsc_run_exclusive failed %d", __func__, ret);
264 return ret;
265 }
Benoit Gobycdd61b32012-07-09 12:09:59 -0700266
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700267 return 0;
Benoit Gobycdd61b32012-07-09 12:09:59 -0700268}
269
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700270bool exynos5_supports_overlay(hwc_layer_1_t &layer, size_t i)
271{
272 private_handle_t *handle = private_handle_t::dynamicCast(layer.handle);
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700273
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700274 if (!handle) {
275 ALOGV("\tlayer %u: handle is NULL", i);
276 return false;
277 }
278 if (!exynos5_format_is_supported(handle->format)) {
279 ALOGV("\tlayer %u: pixel format %u not supported", i,
280 handle->format);
281 return false;
282 }
283 if (is_scaled(layer)) {
284 ALOGV("\tlayer %u: scaling not supported", i);
285 return false;
286 }
287 if (is_transformed(layer)) {
288 ALOGV("\tlayer %u: transformations not supported", i);
289 return false;
290 }
291 if (layer.blending != HWC_BLENDING_NONE) {
292 // TODO: support this
293 ALOGV("\tlayer %u: blending not supported", i);
294 return false;
295 }
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700296
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700297 return true;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700298}
299
Greg Hackmann31991d52012-07-13 13:23:11 -0700300inline bool intersect(const hwc_rect &r1, const hwc_rect &r2)
301{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700302 return !(r1.left > r2.right ||
303 r1.right < r2.left ||
304 r1.top > r2.bottom ||
305 r1.bottom < r2.top);
Greg Hackmann31991d52012-07-13 13:23:11 -0700306}
307
308inline hwc_rect intersection(const hwc_rect &r1, const hwc_rect &r2)
309{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700310 hwc_rect i;
311 i.top = max(r1.top, r2.top);
312 i.bottom = min(r1.bottom, r2.bottom);
313 i.left = max(r1.left, r2.left);
314 i.right = min(r1.right, r2.right);
315 return i;
Greg Hackmann31991d52012-07-13 13:23:11 -0700316}
317
Erik Gilling87e707e2012-06-29 17:35:13 -0700318static int exynos5_prepare(hwc_composer_device_1_t *dev, hwc_layer_list_1_t* list)
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700319{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700320 if (!list)
321 return 0;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700322
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700323 ALOGV("preparing %u layers", list->numHwLayers);
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700324
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700325 exynos5_hwc_composer_device_1_t *pdev =
326 (exynos5_hwc_composer_device_1_t *)dev;
327 memset(pdev->bufs.overlays, 0, sizeof(pdev->bufs.overlays));
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700328
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700329 bool force_fb = false;
330 if (pdev->hdmi_hpd) {
331 hdmi_enable(pdev);
332 force_fb = true;
333 } else {
334 hdmi_disable(pdev);
335 }
Benoit Gobycdd61b32012-07-09 12:09:59 -0700336
Erik Gilling87e707e2012-06-29 17:35:13 -0700337 for (size_t i = 0; i < NUM_HW_WINDOWS; i++)
338 pdev->bufs.overlay_map[i] = -1;
339
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700340 bool fb_needed = false;
341 size_t first_fb = 0, last_fb = 0;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700342
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700343 // find unsupported overlays
344 for (size_t i = 0; i < list->numHwLayers; i++) {
345 hwc_layer_1_t &layer = list->hwLayers[i];
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700346
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700347 if (layer.compositionType == HWC_BACKGROUND && !force_fb) {
348 ALOGV("\tlayer %u: background supported", i);
349 continue;
350 }
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700351
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700352 if (exynos5_supports_overlay(list->hwLayers[i], i) && !force_fb) {
353 ALOGV("\tlayer %u: overlay supported", i);
354 layer.compositionType = HWC_OVERLAY;
355 continue;
356 }
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700357
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700358 if (!fb_needed) {
359 first_fb = i;
360 fb_needed = true;
361 }
362 last_fb = i;
363 layer.compositionType = HWC_FRAMEBUFFER;
364 }
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700365
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700366 // can't composite overlays sandwiched between framebuffers
367 if (fb_needed)
368 for (size_t i = first_fb; i < last_fb; i++)
369 list->hwLayers[i].compositionType = HWC_FRAMEBUFFER;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700370
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700371 // Incrementally try to add our supported layers to hardware windows.
372 // If adding a layer would violate a hardware constraint, force it
373 // into the framebuffer and try again. (Revisiting the entire list is
374 // necessary because adding a layer to the framebuffer can cause other
375 // windows to retroactively violate constraints.)
376 bool changed;
377 do {
378 android::Vector<hwc_rect> rects;
379 android::Vector<hwc_rect> overlaps;
380 size_t pixels_left, windows_left;
Greg Hackmann31991d52012-07-13 13:23:11 -0700381
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700382 if (fb_needed) {
383 hwc_rect_t fb_rect;
384 fb_rect.top = fb_rect.left = 0;
385 fb_rect.right = pdev->gralloc_module->xres - 1;
386 fb_rect.bottom = pdev->gralloc_module->yres - 1;
387 pixels_left = MAX_PIXELS - pdev->gralloc_module->xres *
388 pdev->gralloc_module->yres;
389 windows_left = NUM_HW_WINDOWS - 1;
390 rects.push_back(fb_rect);
391 }
392 else {
393 pixels_left = MAX_PIXELS;
394 windows_left = NUM_HW_WINDOWS;
395 }
396 changed = false;
Greg Hackmann31991d52012-07-13 13:23:11 -0700397
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700398 for (size_t i = 0; i < list->numHwLayers; i++) {
399 hwc_layer_1_t &layer = list->hwLayers[i];
Greg Hackmann31991d52012-07-13 13:23:11 -0700400
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700401 // we've already accounted for the framebuffer above
402 if (layer.compositionType == HWC_FRAMEBUFFER)
403 continue;
Greg Hackmann31991d52012-07-13 13:23:11 -0700404
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700405 // only layer 0 can be HWC_BACKGROUND, so we can
406 // unconditionally allow it without extra checks
407 if (layer.compositionType == HWC_BACKGROUND) {
408 windows_left--;
409 continue;
410 }
Greg Hackmann31991d52012-07-13 13:23:11 -0700411
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700412 size_t pixels_needed = WIDTH(layer.displayFrame) *
413 HEIGHT(layer.displayFrame);
414 bool can_compose = windows_left && pixels_needed <= pixels_left;
Greg Hackmann31991d52012-07-13 13:23:11 -0700415
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700416 // hwc_rect_t right and bottom values are normally exclusive;
417 // the intersection logic is simpler if we make them inclusive
418 hwc_rect_t visible_rect = layer.displayFrame;
419 visible_rect.right--; visible_rect.bottom--;
Greg Hackmann31991d52012-07-13 13:23:11 -0700420
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700421 // no more than 2 layers can overlap on a given pixel
422 for (size_t j = 0; can_compose && j < overlaps.size(); j++) {
423 if (intersect(visible_rect, overlaps.itemAt(j)))
424 can_compose = false;
425 }
Greg Hackmann31991d52012-07-13 13:23:11 -0700426
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700427 if (!can_compose) {
428 layer.compositionType = HWC_FRAMEBUFFER;
429 if (!fb_needed) {
430 first_fb = last_fb = i;
431 fb_needed = true;
432 }
433 else {
434 first_fb = min(i, first_fb);
435 last_fb = max(i, last_fb);
436 }
437 changed = true;
438 break;
439 }
Greg Hackmann31991d52012-07-13 13:23:11 -0700440
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700441 for (size_t j = 0; j < rects.size(); j++) {
442 const hwc_rect_t &other_rect = rects.itemAt(j);
443 if (intersect(visible_rect, other_rect))
444 overlaps.push_back(intersection(visible_rect, other_rect));
445 }
446 rects.push_back(visible_rect);
447 pixels_left -= pixels_needed;
448 windows_left--;
449 }
Greg Hackmann31991d52012-07-13 13:23:11 -0700450
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700451 if (changed)
452 for (size_t i = first_fb; i < last_fb; i++)
453 list->hwLayers[i].compositionType = HWC_FRAMEBUFFER;
454 } while(changed);
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700455
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700456 unsigned int nextWindow = 0;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700457
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700458 for (size_t i = 0; i < list->numHwLayers; i++) {
459 hwc_layer_1_t &layer = list->hwLayers[i];
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700460
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700461 if (fb_needed && i == first_fb) {
462 ALOGV("assigning framebuffer to window %u\n",
463 nextWindow);
464 nextWindow++;
465 continue;
466 }
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700467
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700468 if (layer.compositionType != HWC_FRAMEBUFFER) {
469 ALOGV("assigning layer %u to window %u", i, nextWindow);
470 pdev->bufs.overlay_map[nextWindow] = i;
471 nextWindow++;
472 }
473 }
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700474
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700475 if (fb_needed)
476 pdev->bufs.fb_window = first_fb;
477 else
478 pdev->bufs.fb_window = NO_FB_NEEDED;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700479
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700480 for (size_t i = 0; i < list->numHwLayers; i++) {
481 dump_layer(&list->hwLayers[i]);
482 if(list->hwLayers[i].handle)
483 dump_handle(private_handle_t::dynamicCast(
484 list->hwLayers[i].handle));
485 }
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700486
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700487 return 0;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700488}
489
490static void exynos5_config_handle(private_handle_t *handle,
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700491 hwc_rect_t &sourceCrop, hwc_rect_t &displayFrame,
492 s3c_fb_win_config &cfg)
493{
494 cfg.state = cfg.S3C_FB_WIN_STATE_BUFFER;
495 cfg.fd = handle->fd;
496 cfg.x = displayFrame.left;
497 cfg.y = displayFrame.top;
498 cfg.w = WIDTH(displayFrame);
499 cfg.h = HEIGHT(displayFrame);
500 cfg.format = exynos5_format_to_s3c_format(handle->format);
501 uint8_t bpp = exynos5_format_to_bpp(handle->format);
502 cfg.offset = (sourceCrop.top * handle->stride + sourceCrop.left) * bpp / 8;
503 cfg.stride = handle->stride * bpp / 8;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700504}
505
Erik Gilling87e707e2012-06-29 17:35:13 -0700506static void exynos5_config_overlay(hwc_layer_1_t *layer, s3c_fb_win_config &cfg,
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700507 const private_module_t *gralloc_module)
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700508{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700509 if (layer->compositionType == HWC_BACKGROUND) {
510 hwc_color_t color = layer->backgroundColor;
511 cfg.state = cfg.S3C_FB_WIN_STATE_COLOR;
512 cfg.color = (color.r << 16) | (color.g << 8) | color.b;
513 cfg.x = 0;
514 cfg.y = 0;
515 cfg.w = gralloc_module->xres;
516 cfg.h = gralloc_module->yres;
517 return;
518 }
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700519
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700520 private_handle_t *handle = private_handle_t::dynamicCast(layer->handle);
521 exynos5_config_handle(handle, layer->sourceCrop, layer->displayFrame, cfg);
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700522}
523
524static void exynos5_post_callback(void *data, private_handle_t *fb)
525{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700526 exynos5_hwc_post_data_t *pdata = (exynos5_hwc_post_data_t *)data;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700527
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700528 struct s3c_fb_win_config_data win_data;
529 struct s3c_fb_win_config *config = win_data.config;
530 memset(config, 0, sizeof(win_data.config));
531 for (size_t i = 0; i < NUM_HW_WINDOWS; i++) {
532 if (i == pdata->fb_window) {
533 hwc_rect_t rect = { 0, 0, fb->width, fb->height };
534 exynos5_config_handle(fb, rect, rect, config[i]);
535 } else if ( pdata->overlay_map[i] != -1) {
536 exynos5_config_overlay(&pdata->overlays[i], config[i],
537 pdata->pdev->gralloc_module);
Erik Gilling87e707e2012-06-29 17:35:13 -0700538 if (pdata->overlays[i].acquireFenceFd != -1) {
539 int err = sync_wait(pdata->overlays[i].acquireFenceFd, 100);
540 if (err != 0)
541 ALOGW("fence for layer %zu didn't signal in 100 ms: %s",
542 i, strerror(errno));
543 close(pdata->overlays[i].acquireFenceFd);
544 }
545 }
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700546 dump_config(config[i]);
547 }
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700548
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700549 int ret = ioctl(pdata->pdev->fd, S3CFB_WIN_CONFIG, &win_data);
550 if (ret < 0)
551 ALOGE("ioctl S3CFB_WIN_CONFIG failed: %d", errno);
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700552
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700553 if (pdata->pdev->hdmi_mirroring)
554 hdmi_output(pdata->pdev, fb);
Benoit Gobycdd61b32012-07-09 12:09:59 -0700555
Erik Gilling87e707e2012-06-29 17:35:13 -0700556 pthread_mutex_lock(&pdata->completion_lock);
557 pdata->fence = win_data.fence;
558 pthread_cond_signal(&pdata->completion);
559 pthread_mutex_unlock(&pdata->completion_lock);
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700560}
561
Erik Gilling87e707e2012-06-29 17:35:13 -0700562static int exynos5_set(struct hwc_composer_device_1 *dev, hwc_display_t dpy,
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700563 hwc_surface_t sur, hwc_layer_list_1_t* list)
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700564{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700565 exynos5_hwc_composer_device_1_t *pdev =
566 (exynos5_hwc_composer_device_1_t *)dev;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700567
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700568 if (!dpy || !sur)
569 return 0;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700570
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700571 hwc_callback_queue_t *queue = NULL;
572 pthread_mutex_t *lock = NULL;
573 exynos5_hwc_post_data_t *data = NULL;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700574
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700575 if (list) {
Erik Gilling87e707e2012-06-29 17:35:13 -0700576 for (size_t i = 0; i < NUM_HW_WINDOWS; i++) {
577 if (pdev->bufs.overlay_map[i] != -1) {
578 pdev->bufs.overlays[i] =
579 list->hwLayers[pdev->bufs.overlay_map[i]];
580 }
581 }
582
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700583 data = (exynos5_hwc_post_data_t *)
584 malloc(sizeof(exynos5_hwc_post_data_t));
585 memcpy(data, &pdev->bufs, sizeof(pdev->bufs));
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700586
Erik Gilling87e707e2012-06-29 17:35:13 -0700587 data->fence = -1;
588 pthread_mutex_init(&data->completion_lock, NULL);
589 pthread_cond_init(&data->completion, NULL);
590
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700591 if (pdev->bufs.fb_window == NO_FB_NEEDED) {
592 exynos5_post_callback(data, NULL);
593 } else {
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700594
Erik Gilling87e707e2012-06-29 17:35:13 -0700595 struct hwc_callback_entry entry;
596 entry.callback = exynos5_post_callback;
597 entry.data = data;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700598
Erik Gilling87e707e2012-06-29 17:35:13 -0700599 queue = reinterpret_cast<hwc_callback_queue_t *>(
600 pdev->gralloc_module->queue);
601 lock = const_cast<pthread_mutex_t *>(
602 &pdev->gralloc_module->queue_lock);
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700603
Erik Gilling87e707e2012-06-29 17:35:13 -0700604 pthread_mutex_lock(lock);
605 queue->push_front(entry);
606 pthread_mutex_unlock(lock);
607
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700608 EGLBoolean success = eglSwapBuffers((EGLDisplay)dpy,
609 (EGLSurface)sur);
Erik Gilling87e707e2012-06-29 17:35:13 -0700610 if (!success) {
611 ALOGE("HWC_EGL_ERROR");
612 if (list) {
613 pthread_mutex_lock(lock);
614 queue->removeAt(0);
615 pthread_mutex_unlock(lock);
616 free(data);
617 }
618 return HWC_EGL_ERROR;
619 }
620 }
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700621 }
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700622
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700623
Erik Gilling87e707e2012-06-29 17:35:13 -0700624 pthread_mutex_lock(&data->completion_lock);
625 while (data->fence == -1)
626 pthread_cond_wait(&data->completion, &data->completion_lock);
627 pthread_mutex_unlock(&data->completion_lock);
628
629 for (size_t i = 0; i < NUM_HW_WINDOWS; i++) {
630 if (pdev->bufs.overlay_map[i] != -1) {
631 int dup_fd = dup(data->fence);
632 if (dup_fd < 0)
633 ALOGW("release fence dup failed: %s", strerror(errno));
634 list->hwLayers[pdev->bufs.overlay_map[i]].releaseFenceFd = dup_fd;
635 }
636 }
637 close(data->fence);
638 free(data);
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700639 return 0;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700640}
641
Erik Gilling87e707e2012-06-29 17:35:13 -0700642static void exynos5_registerProcs(struct hwc_composer_device_1* dev,
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700643 hwc_procs_t const* procs)
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700644{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700645 struct exynos5_hwc_composer_device_1_t* pdev =
646 (struct exynos5_hwc_composer_device_1_t*)dev;
647 pdev->procs = const_cast<hwc_procs_t *>(procs);
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700648}
649
Erik Gilling87e707e2012-06-29 17:35:13 -0700650static int exynos5_query(struct hwc_composer_device_1* dev, int what, int *value)
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700651{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700652 struct exynos5_hwc_composer_device_1_t *pdev =
653 (struct exynos5_hwc_composer_device_1_t *)dev;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700654
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700655 switch (what) {
656 case HWC_BACKGROUND_LAYER_SUPPORTED:
657 // we support the background layer
658 value[0] = 1;
659 break;
660 case HWC_VSYNC_PERIOD:
661 // vsync period in nanosecond
662 value[0] = 1000000000.0 / pdev->gralloc_module->fps;
663 break;
664 default:
665 // unsupported query
666 return -EINVAL;
667 }
668 return 0;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700669}
670
Erik Gilling87e707e2012-06-29 17:35:13 -0700671static int exynos5_eventControl(struct hwc_composer_device_1 *dev, int event,
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700672 int enabled)
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700673{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700674 struct exynos5_hwc_composer_device_1_t *pdev =
675 (struct exynos5_hwc_composer_device_1_t *)dev;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700676
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700677 switch (event) {
678 case HWC_EVENT_VSYNC:
679 __u32 val = !!enabled;
680 int err = ioctl(pdev->fd, S3CFB_SET_VSYNC_INT, &val);
681 if (err < 0) {
682 ALOGE("vsync ioctl failed");
683 return -errno;
684 }
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700685
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700686 return 0;
687 }
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700688
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700689 return -EINVAL;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700690}
691
Benoit Gobycdd61b32012-07-09 12:09:59 -0700692static void handle_hdmi_uevent(struct exynos5_hwc_composer_device_1_t *pdev,
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700693 const char *buff, int len)
Benoit Gobycdd61b32012-07-09 12:09:59 -0700694{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700695 const char *s = buff;
696 s += strlen(s) + 1;
Benoit Gobycdd61b32012-07-09 12:09:59 -0700697
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700698 while (*s) {
699 if (!strncmp(s, "SWITCH_STATE=", strlen("SWITCH_STATE=")))
700 pdev->hdmi_hpd = atoi(s + strlen("SWITCH_STATE=")) == 1;
Benoit Gobycdd61b32012-07-09 12:09:59 -0700701
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700702 s += strlen(s) + 1;
703 if (s - buff >= len)
704 break;
705 }
Benoit Gobycdd61b32012-07-09 12:09:59 -0700706
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700707 ALOGV("HDMI HPD changed to %s", pdev->hdmi_hpd ? "enabled" : "disabled");
Benoit Gobycdd61b32012-07-09 12:09:59 -0700708
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700709 if (pdev->procs && pdev->procs->invalidate)
710 pdev->procs->invalidate(pdev->procs);
Benoit Gobycdd61b32012-07-09 12:09:59 -0700711}
712
Greg Hackmann29724852012-07-23 15:31:10 -0700713static void handle_vsync_event(struct exynos5_hwc_composer_device_1_t *pdev)
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700714{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700715 if (!pdev->procs || !pdev->procs->vsync)
716 return;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700717
Greg Hackmann29724852012-07-23 15:31:10 -0700718 char buf[4096];
719 int err = read(pdev->vsync_fd, buf, sizeof(buf));
720 if (err < 0) {
721 ALOGE("error reading vsync timestamp: %s", strerror(errno));
722 return;
Greg Hackmann3464b1d2012-07-24 09:46:23 -0700723 }
Greg Hackmann29724852012-07-23 15:31:10 -0700724 buf[sizeof(buf) - 1] = '\0';
Greg Hackmann3464b1d2012-07-24 09:46:23 -0700725
Greg Hackmann29724852012-07-23 15:31:10 -0700726 errno = 0;
727 uint64_t timestamp = strtoull(buf, NULL, 0);
728 if (!errno)
729 pdev->procs->vsync(pdev->procs, 0, timestamp);
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700730}
731
732static void *hwc_vsync_thread(void *data)
733{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700734 struct exynos5_hwc_composer_device_1_t *pdev =
735 (struct exynos5_hwc_composer_device_1_t *)data;
736 char uevent_desc[4096];
737 memset(uevent_desc, 0, sizeof(uevent_desc));
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700738
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700739 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700740
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700741 uevent_init();
Greg Hackmann29724852012-07-23 15:31:10 -0700742
743 struct pollfd fds[2];
744 fds[0].fd = pdev->vsync_fd;
745 fds[0].events = POLLPRI;
746 fds[1].fd = uevent_get_fd();
747 fds[1].events = POLLIN;
748
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700749 while (true) {
Greg Hackmann29724852012-07-23 15:31:10 -0700750 int err = poll(fds, 2, -1);
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700751
Greg Hackmann29724852012-07-23 15:31:10 -0700752 if (err > 0) {
753 if (fds[0].revents & POLLPRI) {
754 handle_vsync_event(pdev);
755 }
756 else if (fds[1].revents & POLLIN) {
757 int len = uevent_next_event(uevent_desc,
758 sizeof(uevent_desc) - 2);
Benoit Gobycdd61b32012-07-09 12:09:59 -0700759
Greg Hackmann29724852012-07-23 15:31:10 -0700760 bool hdmi = !strcmp(uevent_desc,
761 "change@/devices/virtual/switch/hdmi");
762 if (hdmi)
763 handle_hdmi_uevent(pdev, uevent_desc, len);
764 }
765 }
766 else if (err == -1) {
767 if (errno == EINTR)
768 break;
769 ALOGE("error in vsync thread: %s", strerror(errno));
770 }
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700771 }
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700772
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700773 return NULL;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700774}
775
Colin Cross00359a82012-07-12 17:54:17 -0700776static int exynos5_blank(struct hwc_composer_device_1 *dev, int blank)
777{
778 struct exynos5_hwc_composer_device_1_t *pdev =
779 (struct exynos5_hwc_composer_device_1_t *)dev;
780
781 int fb_blank = blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK;
782 int err = ioctl(pdev->fd, FBIOBLANK, fb_blank);
783 if (err < 0) {
784 ALOGE("%sblank ioctl failed", blank ? "" : "un");
785 return -errno;
786 }
787
788 return 0;
789}
790
Erik Gilling87e707e2012-06-29 17:35:13 -0700791struct hwc_methods_1 exynos5_methods = {
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700792 eventControl: exynos5_eventControl,
Colin Cross00359a82012-07-12 17:54:17 -0700793 blank: exynos5_blank,
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700794};
795
796static int exynos5_close(hw_device_t* device);
797
798static int exynos5_open(const struct hw_module_t *module, const char *name,
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700799 struct hw_device_t **device)
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700800{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700801 int ret;
802 int sw_fd;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700803
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700804 if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
805 return -EINVAL;
806 }
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700807
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700808 struct exynos5_hwc_composer_device_1_t *dev;
809 dev = (struct exynos5_hwc_composer_device_1_t *)malloc(sizeof(*dev));
810 memset(dev, 0, sizeof(*dev));
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700811
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700812 if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
813 (const struct hw_module_t **)&dev->gralloc_module)) {
814 ALOGE("failed to get gralloc hw module");
815 ret = -EINVAL;
816 goto err_get_module;
817 }
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700818
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700819 dev->fd = open("/dev/graphics/fb0", O_RDWR);
820 if (dev->fd < 0) {
821 ALOGE("failed to open framebuffer");
822 ret = dev->fd;
823 goto err_get_module;
824 }
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700825
Greg Hackmann29724852012-07-23 15:31:10 -0700826 dev->vsync_fd = open("/sys/devices/platform/exynos5-fb.1/vsync", O_RDONLY);
827 if (dev->vsync_fd < 0) {
828 ALOGE("failed to open vsync attribute");
829 ret = dev->vsync_fd;
830 goto err_ioctl;
831 }
832
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700833 sw_fd = open("/sys/class/switch/hdmi/state", O_RDONLY);
834 if (sw_fd) {
835 char val;
836 if (read(sw_fd, &val, 1) == 1 && val == '1')
837 dev->hdmi_hpd = true;
838 }
Benoit Gobycdd61b32012-07-09 12:09:59 -0700839
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700840 dev->base.common.tag = HARDWARE_DEVICE_TAG;
841 dev->base.common.version = HWC_DEVICE_API_VERSION_1_0;
842 dev->base.common.module = const_cast<hw_module_t *>(module);
843 dev->base.common.close = exynos5_close;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700844
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700845 dev->base.prepare = exynos5_prepare;
846 dev->base.set = exynos5_set;
847 dev->base.registerProcs = exynos5_registerProcs;
848 dev->base.query = exynos5_query;
849 dev->base.methods = &exynos5_methods;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700850
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700851 dev->bufs.pdev = dev;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700852
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700853 *device = &dev->base.common;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700854
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700855 ret = pthread_create(&dev->vsync_thread, NULL, hwc_vsync_thread, dev);
856 if (ret) {
857 ALOGE("failed to start vsync thread: %s", strerror(ret));
858 ret = -ret;
Greg Hackmann29724852012-07-23 15:31:10 -0700859 goto err_vsync;
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700860 }
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700861
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700862 return 0;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700863
Greg Hackmann29724852012-07-23 15:31:10 -0700864err_vsync:
865 close(dev->vsync_fd);
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700866err_ioctl:
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700867 close(dev->fd);
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700868err_get_module:
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700869 free(dev);
870 return ret;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700871}
872
873static int exynos5_close(hw_device_t *device)
874{
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700875 struct exynos5_hwc_composer_device_1_t *dev =
876 (struct exynos5_hwc_composer_device_1_t *)device;
Greg Hackmann29724852012-07-23 15:31:10 -0700877 pthread_kill(dev->vsync_thread, SIGTERM);
878 pthread_join(dev->vsync_thread, NULL);
879 close(dev->vsync_fd);
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700880 close(dev->fd);
881 return 0;
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700882}
883
884static struct hw_module_methods_t exynos5_hwc_module_methods = {
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700885 open: exynos5_open,
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700886};
887
888hwc_module_t HAL_MODULE_INFO_SYM = {
Greg Hackmannf6f2e542012-07-16 16:10:27 -0700889 common: {
890 tag: HARDWARE_MODULE_TAG,
891 module_api_version: HWC_MODULE_API_VERSION_0_1,
892 hal_api_version: HARDWARE_HAL_API_VERSION,
893 id: HWC_HARDWARE_MODULE_ID,
894 name: "Samsung exynos5 hwcomposer module",
895 author: "Google",
896 methods: &exynos5_hwc_module_methods,
897 }
Greg Hackmann86eb1c62012-05-30 09:25:51 -0700898};