hwc.c revision 2acde915b4868129963ef7dc7afe1f3b35ffeeac
1/* 2 * Copyright (C) Texas Instruments - http://www.ti.com/ 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <errno.h> 18#include <malloc.h> 19#include <stdlib.h> 20#include <stdarg.h> 21#include <fcntl.h> 22#include <poll.h> 23#include <sys/eventfd.h> 24#include <sys/ioctl.h> 25#include <linux/fb.h> 26#include <linux/omapfb.h> 27#include <sys/mman.h> 28#include <sys/resource.h> 29 30#include <cutils/properties.h> 31#include <cutils/log.h> 32#include <cutils/native_handle.h> 33#define HWC_REMOVE_DEPRECATED_VERSIONS 0 34#include <hardware/hardware.h> 35#include <hardware/hwcomposer.h> 36#include <EGL/egl.h> 37#include <hardware_legacy/uevent.h> 38#include <png.h> 39#include <utils/Timers.h> 40 41#include <system/graphics.h> 42#include <linux/bltsville.h> 43 44#define MAX_HWC_LAYERS 32 45 46#define ASPECT_RATIO_TOLERANCE 0.02f 47 48#define min(a, b) ( { typeof(a) __a = (a), __b = (b); __a < __b ? __a : __b; } ) 49#define max(a, b) ( { typeof(a) __a = (a), __b = (b); __a > __b ? __a : __b; } ) 50#define swap(a, b) do { typeof(a) __a = (a); (a) = (b); (b) = __a; } while (0) 51 52#define WIDTH(rect) ((rect).right - (rect).left) 53#define HEIGHT(rect) ((rect).bottom - (rect).top) 54 55#define DIV_ROUND_UP(a, b) (((a) + (b) - 1) / (b)) 56 57#include <video/dsscomp.h> 58#include <video/omap_hwc.h> 59 60#include "hal_public.h" 61#include "rgz_2d.h" 62 63#include <linux/ion.h> 64#include <linux/omap_ion.h> 65#include <ion/ion.h> 66 67#define MAX_HW_OVERLAYS 4 68#define NUM_NONSCALING_OVERLAYS 1 69#define NUM_EXT_DISPLAY_BACK_BUFFERS 2 70 71struct ext_transform_t { 72 __u8 rotation : 3; /* 90-degree clockwise rotations */ 73 __u8 hflip : 1; /* flip l-r (after rotation) */ 74 __u8 enabled : 1; /* cloning enabled */ 75 __u8 docking : 1; /* docking vs. mirroring - used for state */ 76}; 77 78/* cloning support and state */ 79struct omap4_hwc_ext { 80 /* support */ 81 struct ext_transform_t mirror; /* mirroring settings */ 82 struct ext_transform_t dock; /* docking settings */ 83 float lcd_xpy; /* pixel ratio for UI */ 84 __u8 avoid_mode_change; /* use HDMI mode used for mirroring if possible */ 85 __u8 force_dock; /* must dock */ 86 __u8 hdmi_state; /* whether HDMI is connected */ 87 88 /* state */ 89 __u8 on_tv; /* using a tv */ 90 struct ext_transform_t current; /* current settings */ 91 struct ext_transform_t last; /* last-used settings */ 92 93 /* configuration */ 94 __u32 last_xres_used; /* resolution and pixel ratio used for mode selection */ 95 __u32 last_yres_used; 96 __u32 last_mode; /* 2-s complement of last HDMI mode set, 0 if none */ 97 __u32 mirror_mode; /* 2-s complement of mode used when mirroring */ 98 float last_xpy; 99 __u16 width; /* external screen dimensions */ 100 __u16 height; 101 __u32 xres; /* external screen resolution */ 102 __u32 yres; 103 float m[2][3]; /* external transformation matrix */ 104 hwc_rect_t mirror_region; /* region of screen to mirror */ 105}; 106typedef struct omap4_hwc_ext omap4_hwc_ext_t; 107 108/* used by property settings */ 109enum { 110 EXT_ROTATION = 3, /* rotation while mirroring */ 111 EXT_HFLIP = (1 << 2), /* flip l-r on output (after rotation) */ 112}; 113 114enum bltpolicy { 115 BLTPOLICY_DISABLED = 0, 116 BLTPOLICY_DEFAULT = 1, /* Default blit policy */ 117 BLTPOLICY_ALL, /* Test mode to attempt to blit all */ 118}; 119 120enum bltmode { 121 BLTMODE_PAINT = 0, /* Attempt to blit layer by layer */ 122 BLTMODE_REGION = 1, /* Attempt to blit layers via regions */ 123}; 124 125/* ARGB image */ 126struct omap4_hwc_img { 127 int width; 128 int height; 129 int rowbytes; 130 int size; 131 unsigned char *ptr; 132} dock_image = { .rowbytes = 0 }; 133 134struct omap4_hwc_module { 135 hwc_module_t base; 136 137 IMG_framebuffer_device_public_t *fb_dev; 138}; 139typedef struct omap4_hwc_module omap4_hwc_module_t; 140 141struct counts { 142 unsigned int possible_overlay_layers; 143 unsigned int composited_layers; 144 unsigned int scaled_layers; 145 unsigned int RGB; 146 unsigned int BGR; 147 unsigned int NV12; 148 unsigned int dockable; 149 unsigned int protected; 150 151 unsigned int max_hw_overlays; 152 unsigned int max_scaling_overlays; 153 unsigned int mem; 154 unsigned int s3d; 155}; 156 157struct omap4_hwc_device { 158 /* static data */ 159 hwc_composer_device_1_t base; 160 hwc_procs_t *procs; 161 pthread_t hdmi_thread; 162 pthread_mutex_t lock; 163 164 IMG_framebuffer_device_public_t *fb_dev; 165 struct dsscomp_display_info fb_dis; 166 int fb_fd; /* file descriptor for /dev/fb0 */ 167 int dsscomp_fd; /* file descriptor for /dev/dsscomp */ 168 int hdmi_fb_fd; /* file descriptor for /dev/fb1 */ 169 int wakeup_evt; /* eventfd used to wakeup event thread */ 170 171 int img_mem_size; /* size of fb for hdmi */ 172 void *img_mem_ptr; /* start of fb for hdmi */ 173 174 int flags_rgb_order; 175 int flags_nv12_only; 176 float upscaled_nv12_limit; 177 178 int on_tv; /* using a tv */ 179 int force_sgx; 180 omap4_hwc_ext_t ext; /* external mirroring data */ 181 int idle; 182 183 float primary_m[2][3]; /* internal transformation matrix */ 184 int primary_transform; 185 int primary_rotation; 186 hwc_rect_t primary_region; 187 188 buffer_handle_t *buffers; 189 int use_sgx; 190 int swap_rb; 191 unsigned int post2_layers; /* Buffers used with DSS pipes*/ 192 unsigned int post2_blit_buffers; /* Buffers used with blit */ 193 int ext_ovls; /* # of overlays on external display for current composition */ 194 int ext_ovls_wanted; /* # of overlays that should be on external display for current composition */ 195 int last_ext_ovls; /* # of overlays on external/internal display for last composition */ 196 int last_int_ovls; 197 198 enum bltmode blt_mode; 199 enum bltpolicy blt_policy; 200 201 int blit_flags; 202 int blit_num; 203 struct omap_hwc_data comp_data; /* This is a kernel data structure */ 204 struct rgz_blt_entry blit_ops[RGZ_MAX_BLITS]; 205 struct counts stats; 206 int ion_fd; 207 struct ion_handle *ion_handles[2]; 208 209 /* fake vsync event state */ 210 pthread_mutex_t vsync_lock; 211 int vsync_enabled; 212 uint64_t last_vsync_time; 213 int last_vsync_time_valid; 214 uint64_t fake_vsync_period; 215}; 216typedef struct omap4_hwc_device omap4_hwc_device_t; 217 218#define HAL_FMT(f) ((f) == HAL_PIXEL_FORMAT_TI_NV12 ? "NV12" : \ 219 (f) == HAL_PIXEL_FORMAT_TI_NV12_1D ? "NV12" : \ 220 (f) == HAL_PIXEL_FORMAT_YV12 ? "YV12" : \ 221 (f) == HAL_PIXEL_FORMAT_BGRX_8888 ? "xRGB32" : \ 222 (f) == HAL_PIXEL_FORMAT_RGBX_8888 ? "xBGR32" : \ 223 (f) == HAL_PIXEL_FORMAT_BGRA_8888 ? "ARGB32" : \ 224 (f) == HAL_PIXEL_FORMAT_RGBA_8888 ? "ABGR32" : \ 225 (f) == HAL_PIXEL_FORMAT_RGB_565 ? "RGB565" : "??") 226 227#define DSS_FMT(f) ((f) == OMAP_DSS_COLOR_NV12 ? "NV12" : \ 228 (f) == OMAP_DSS_COLOR_RGB24U ? "xRGB32" : \ 229 (f) == OMAP_DSS_COLOR_ARGB32 ? "ARGB32" : \ 230 (f) == OMAP_DSS_COLOR_RGB16 ? "RGB565" : "??") 231 232static int debug = 0; 233static int debugpost2 = 0; 234static int debugblt = 0; 235static rgz_t grgz; 236static struct bvsurfgeom gscrngeom; 237 238static void showfps(void) 239{ 240 static int framecount = 0; 241 static int lastframecount = 0; 242 static nsecs_t lastfpstime = 0; 243 static float fps = 0; 244 char value[PROPERTY_VALUE_MAX]; 245 246 property_get("debug.hwc.showfps", value, "0"); 247 if (!atoi(value)) { 248 return; 249 } 250 251 framecount++; 252 if (!(framecount & 0x7)) { 253 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); 254 nsecs_t diff = now - lastfpstime; 255 fps = ((framecount - lastframecount) * (float)(s2ns(1))) / diff; 256 lastfpstime = now; 257 lastframecount = framecount; 258 ALOGI("%d Frames, %f FPS", framecount, fps); 259 } 260} 261 262static void dump_layer(hwc_layer_1_t const* l) 263{ 264 ALOGD("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}", 265 l->compositionType, l->flags, l->handle, l->transform, l->blending, 266 l->sourceCrop.left, 267 l->sourceCrop.top, 268 l->sourceCrop.right, 269 l->sourceCrop.bottom, 270 l->displayFrame.left, 271 l->displayFrame.top, 272 l->displayFrame.right, 273 l->displayFrame.bottom); 274} 275 276static void dump_dsscomp(struct dsscomp_setup_dispc_data *d) 277{ 278 unsigned i; 279 280 ALOGD("[%08x] set: %c%c%c %d ovls\n", 281 d->sync_id, 282 (d->mode & DSSCOMP_SETUP_MODE_APPLY) ? 'A' : '-', 283 (d->mode & DSSCOMP_SETUP_MODE_DISPLAY) ? 'D' : '-', 284 (d->mode & DSSCOMP_SETUP_MODE_CAPTURE) ? 'C' : '-', 285 d->num_ovls); 286 287 for (i = 0; i < d->num_mgrs; i++) { 288 struct dss2_mgr_info *mi = &d->mgrs[i]; 289 ALOGD(" (dis%d alpha=%d col=%08x ilace=%d)\n", 290 mi->ix, 291 mi->alpha_blending, mi->default_color, 292 mi->interlaced); 293 } 294 295 for (i = 0; i < d->num_ovls; i++) { 296 struct dss2_ovl_info *oi = &d->ovls[i]; 297 struct dss2_ovl_cfg *c = &oi->cfg; 298 if (c->zonly) 299 ALOGD("ovl%d(%s z%d)\n", 300 c->ix, c->enabled ? "ON" : "off", c->zorder); 301 else 302 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", 303 c->ix, c->enabled ? "ON" : "off", c->zorder, DSS_FMT(c->color_mode), 304 c->pre_mult_alpha ? " premult" : "", 305 (c->global_alpha * 100 + 128) / 255, 306 c->width, c->height, c->crop.x, c->crop.y, 307 c->crop.w, c->crop.h, 308 c->rotation, c->mirror ? "+mir" : "", 309 c->win.x, c->win.y, c->win.w, c->win.h, 310 (void *) oi->ba, (void *) oi->uv, c->stride); 311 } 312} 313 314struct dump_buf { 315 char *buf; 316 int buf_len; 317 int len; 318}; 319 320static void dump_printf(struct dump_buf *buf, const char *fmt, ...) 321{ 322 va_list ap; 323 324 va_start(ap, fmt); 325 buf->len += vsnprintf(buf->buf + buf->len, buf->buf_len - buf->len, fmt, ap); 326 va_end(ap); 327} 328 329static void dump_set_info(omap4_hwc_device_t *hwc_dev, hwc_display_contents_1_t* list) 330{ 331 struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->comp_data.dsscomp_data; 332 char logbuf[1024]; 333 struct dump_buf log = { 334 .buf = logbuf, 335 .buf_len = sizeof(logbuf), 336 }; 337 unsigned int i; 338 339 dump_printf(&log, "set H{"); 340 for (i = 0; list && i < list->numHwLayers; i++) { 341 if (i) 342 dump_printf(&log, " "); 343 hwc_layer_1_t *layer = &list->hwLayers[i]; 344 IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; 345 if (hwc_dev->post2_blit_buffers) { 346 if ((i + 1) < hwc_dev->post2_layers) 347 dump_printf(&log, "%p:%s,", handle, "DSS"); 348 else 349 dump_printf(&log, "%p:%s,", handle, "BV2D"); 350 } 351 else 352 dump_printf(&log, "%p:%s,", handle, layer->compositionType == HWC_OVERLAY ? "DSS" : "SGX"); 353 if ((layer->flags & HWC_SKIP_LAYER) || !handle) { 354 dump_printf(&log, "SKIP"); 355 continue; 356 } 357 if (layer->flags & HWC_HINT_CLEAR_FB) 358 dump_printf(&log, "CLR,"); 359 dump_printf(&log, "%d*%d(%s)", handle->iWidth, handle->iHeight, HAL_FMT(handle->iFormat)); 360 if (layer->transform) 361 dump_printf(&log, "~%d", layer->transform); 362 } 363 dump_printf(&log, "} D{"); 364 for (i = 0; i < dsscomp->num_ovls; i++) { 365 if (i) 366 dump_printf(&log, " "); 367 dump_printf(&log, "%d=", dsscomp->ovls[i].cfg.ix); 368 if (dsscomp->ovls[i].cfg.enabled) 369 dump_printf(&log, "%08x:%d*%d,%s", 370 dsscomp->ovls[i].ba, 371 dsscomp->ovls[i].cfg.width, 372 dsscomp->ovls[i].cfg.height, 373 DSS_FMT(dsscomp->ovls[i].cfg.color_mode)); 374 else 375 dump_printf(&log, "-"); 376 } 377 dump_printf(&log, "} L{"); 378 for (i = 0; i < hwc_dev->post2_layers; i++) { 379 if (i) 380 dump_printf(&log, " "); 381 dump_printf(&log, "%p", hwc_dev->buffers[i]); 382 } 383 if (hwc_dev->post2_blit_buffers) { 384 dump_printf(&log, "} B{"); 385 for (i = hwc_dev->post2_layers; 386 i < hwc_dev->post2_blit_buffers + hwc_dev->post2_layers; i++) { 387 dump_printf(&log, "%p ", hwc_dev->buffers[i]); 388 } 389 } 390 dump_printf(&log, "}%s\n", hwc_dev->use_sgx ? " swap" : ""); 391 392 ALOGD("%s", log.buf); 393} 394 395static int sync_id = 0; 396 397static int omap4_hwc_is_valid_format(int format) 398{ 399 switch(format) { 400 case HAL_PIXEL_FORMAT_RGB_565: 401 case HAL_PIXEL_FORMAT_RGBX_8888: 402 case HAL_PIXEL_FORMAT_RGBA_8888: 403 case HAL_PIXEL_FORMAT_BGRA_8888: 404 case HAL_PIXEL_FORMAT_BGRX_8888: 405 case HAL_PIXEL_FORMAT_TI_NV12: 406 case HAL_PIXEL_FORMAT_TI_NV12_1D: 407 return 1; 408 409 default: 410 return 0; 411 } 412} 413 414static int scaled(hwc_layer_1_t *layer) 415{ 416 int w = WIDTH(layer->sourceCrop); 417 int h = HEIGHT(layer->sourceCrop); 418 419 if (layer->transform & HWC_TRANSFORM_ROT_90) 420 swap(w, h); 421 422 return WIDTH(layer->displayFrame) != w || HEIGHT(layer->displayFrame) != h; 423} 424 425static int is_protected(hwc_layer_1_t *layer) 426{ 427 IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; 428 429 return (handle->usage & GRALLOC_USAGE_PROTECTED); 430} 431 432#define is_BLENDED(layer) ((layer)->blending != HWC_BLENDING_NONE) 433 434static int is_RGB32(IMG_native_handle_t *handle) 435{ 436 switch(handle->iFormat) 437 { 438 case HAL_PIXEL_FORMAT_BGRA_8888: 439 case HAL_PIXEL_FORMAT_BGRX_8888: 440 return 1; 441 default: 442 return 0; 443 } 444} 445 446static int is_RGB(IMG_native_handle_t *handle) 447{ 448 switch(handle->iFormat) 449 { 450 case HAL_PIXEL_FORMAT_BGRA_8888: 451 case HAL_PIXEL_FORMAT_BGRX_8888: 452 case HAL_PIXEL_FORMAT_RGB_565: 453 return 1; 454 default: 455 return 0; 456 } 457} 458 459static int is_BGR_format(int format) 460{ 461 switch (format) { 462 case HAL_PIXEL_FORMAT_RGBX_8888: 463 case HAL_PIXEL_FORMAT_RGBA_8888: 464 return 1; 465 default: 466 return 0; 467 } 468} 469 470static int is_BGR(IMG_native_handle_t *handle) 471{ 472 return is_BGR_format(handle->iFormat); 473} 474 475static int is_NV12(IMG_native_handle_t *handle) 476{ 477 switch(handle->iFormat) 478 { 479 case HAL_PIXEL_FORMAT_TI_NV12: 480 case HAL_PIXEL_FORMAT_TI_NV12_1D: 481 return 1; 482 default: 483 return 0; 484 } 485} 486 487static int is_upscaled_NV12(omap4_hwc_device_t *hwc_dev, hwc_layer_t *layer) 488{ 489 if (!layer) 490 return 0; 491 492 IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; 493 if (!is_NV12(handle)) 494 return 0; 495 496 int w = WIDTH(layer->sourceCrop); 497 int h = HEIGHT(layer->sourceCrop); 498 499 if (layer->transform & HWC_TRANSFORM_ROT_90) 500 swap(w, h); 501 502 return (WIDTH(layer->displayFrame) >= w * hwc_dev->upscaled_nv12_limit || 503 HEIGHT(layer->displayFrame) >= h * hwc_dev->upscaled_nv12_limit); 504} 505 506static int dockable(hwc_layer_t *layer) 507{ 508 IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; 509 510 return (handle->usage & GRALLOC_USAGE_EXTERNAL_DISP); 511} 512 513static uint64_t vsync_clock_now() 514{ 515 uint64_t now = 0; 516 struct timespec ts; 517 518 if (!clock_gettime(CLOCK_MONOTONIC, &ts)) 519 now = ((uint64_t)ts.tv_sec) * 1000000000ull + ts.tv_nsec; 520 521 return now; 522} 523 524static void wakeup_hdmi_thread(omap4_hwc_device_t *hwc_dev) 525{ 526 uint64_t tmp = 1; 527 write(hwc_dev->wakeup_evt, &tmp, sizeof(tmp)); 528} 529 530static void fire_vsync_event(omap4_hwc_device_t *hwc_dev, uint64_t timestamp) 531{ 532 pthread_mutex_lock(&hwc_dev->vsync_lock); 533 534 hwc_dev->last_vsync_time_valid = 1; 535 hwc_dev->last_vsync_time = timestamp; 536 537 pthread_mutex_unlock(&hwc_dev->vsync_lock); 538 539 if (hwc_dev->procs && hwc_dev->procs->vsync) 540 hwc_dev->procs->vsync(hwc_dev->procs, 0, timestamp); 541} 542 543static unsigned int mem1d(IMG_native_handle_t *handle) 544{ 545 if (handle == NULL || is_NV12(handle)) 546 return 0; 547 548 int bpp = handle->iFormat == HAL_PIXEL_FORMAT_RGB_565 ? 2 : 4; 549 int stride = ALIGN(handle->iWidth, HW_ALIGN) * bpp; 550 return stride * handle->iHeight; 551} 552 553static void 554omap4_hwc_setup_layer_base(struct dss2_ovl_cfg *oc, int index, int format, int blended, int width, int height) 555{ 556 unsigned int bits_per_pixel; 557 558 /* YUV2RGB conversion */ 559 const struct omap_dss_cconv_coefs ctbl_bt601_5 = { 560 298, 409, 0, 298, -208, -100, 298, 0, 517, 0, 561 }; 562 563 /* convert color format */ 564 switch (format) { 565 case HAL_PIXEL_FORMAT_RGBA_8888: 566 case HAL_PIXEL_FORMAT_BGRA_8888: 567 oc->color_mode = OMAP_DSS_COLOR_ARGB32; 568 bits_per_pixel = 32; 569 if (blended) 570 break; 571 572 case HAL_PIXEL_FORMAT_RGBX_8888: 573 case HAL_PIXEL_FORMAT_BGRX_8888: 574 oc->color_mode = OMAP_DSS_COLOR_RGB24U; 575 bits_per_pixel = 32; 576 break; 577 578 case HAL_PIXEL_FORMAT_RGB_565: 579 oc->color_mode = OMAP_DSS_COLOR_RGB16; 580 bits_per_pixel = 16; 581 break; 582 583 case HAL_PIXEL_FORMAT_TI_NV12: 584 case HAL_PIXEL_FORMAT_TI_NV12_1D: 585 oc->color_mode = OMAP_DSS_COLOR_NV12; 586 bits_per_pixel = 8; 587 oc->cconv = ctbl_bt601_5; 588 break; 589 590 default: 591 /* Should have been filtered out */ 592 ALOGV("Unsupported pixel format"); 593 return; 594 } 595 596 oc->width = width; 597 oc->height = height; 598 oc->stride = ALIGN(width, HW_ALIGN) * bits_per_pixel / 8; 599 600 oc->enabled = 1; 601 oc->global_alpha = 255; 602 oc->zorder = index; 603 oc->ix = 0; 604 605 /* defaults for SGX framebuffer renders */ 606 oc->crop.w = oc->win.w = width; 607 oc->crop.h = oc->win.h = height; 608 609 /* for now interlacing and vc1 info is not supplied */ 610 oc->ilace = OMAP_DSS_ILACE_NONE; 611 oc->vc1.enable = 0; 612} 613 614static void 615omap4_hwc_setup_layer(omap4_hwc_device_t *hwc_dev, struct dss2_ovl_info *ovl, 616 hwc_layer_1_t *layer, int index, 617 int format, int width, int height) 618{ 619 struct dss2_ovl_cfg *oc = &ovl->cfg; 620 621 //dump_layer(layer); 622 623 omap4_hwc_setup_layer_base(oc, index, format, is_BLENDED(layer), width, height); 624 625 /* convert transformation - assuming 0-set config */ 626 if (layer->transform & HWC_TRANSFORM_FLIP_H) 627 oc->mirror = 1; 628 if (layer->transform & HWC_TRANSFORM_FLIP_V) { 629 oc->rotation = 2; 630 oc->mirror = !oc->mirror; 631 } 632 if (layer->transform & HWC_TRANSFORM_ROT_90) { 633 oc->rotation += oc->mirror ? -1 : 1; 634 oc->rotation &= 3; 635 } 636 637 oc->pre_mult_alpha = layer->blending == HWC_BLENDING_PREMULT; 638 639 /* display position */ 640 oc->win.x = layer->displayFrame.left; 641 oc->win.y = layer->displayFrame.top; 642 oc->win.w = WIDTH(layer->displayFrame); 643 oc->win.h = HEIGHT(layer->displayFrame); 644 645 /* crop */ 646 oc->crop.x = layer->sourceCrop.left; 647 oc->crop.y = layer->sourceCrop.top; 648 oc->crop.w = WIDTH(layer->sourceCrop); 649 oc->crop.h = HEIGHT(layer->sourceCrop); 650} 651 652const float m_unit[2][3] = { { 1., 0., 0. }, { 0., 1., 0. } }; 653 654static inline void m_translate(float m[2][3], int dx, int dy) 655{ 656 m[0][2] += dx; 657 m[1][2] += dy; 658} 659 660static inline void m_scale1(float m[3], int from, int to) 661{ 662 m[0] = m[0] * to / from; 663 m[1] = m[1] * to / from; 664 m[2] = m[2] * to / from; 665} 666 667static inline void m_scale(float m[2][3], int x_from, int x_to, int y_from, int y_to) 668{ 669 m_scale1(m[0], x_from, x_to); 670 m_scale1(m[1], y_from, y_to); 671} 672 673static void m_rotate(float m[2][3], int quarter_turns) 674{ 675 if (quarter_turns & 2) 676 m_scale(m, 1, -1, 1, -1); 677 if (quarter_turns & 1) { 678 int q; 679 q = m[0][0]; m[0][0] = -m[1][0]; m[1][0] = q; 680 q = m[0][1]; m[0][1] = -m[1][1]; m[1][1] = q; 681 q = m[0][2]; m[0][2] = -m[1][2]; m[1][2] = q; 682 } 683} 684 685static inline int m_round(float x) 686{ 687 /* int truncates towards 0 */ 688 return (int) (x < 0 ? x - 0.5 : x + 0.5); 689} 690 691/* 692 * assuming xpy (xratio:yratio) original pixel ratio, calculate the adjusted width 693 * and height for a screen of xres/yres and physical size of width/height. 694 * The adjusted size is the largest that fits into the screen. 695 */ 696static void get_max_dimensions(__u32 orig_xres, __u32 orig_yres, 697 float xpy, 698 __u32 scr_xres, __u32 scr_yres, 699 __u32 scr_width, __u32 scr_height, 700 __u32 *adj_xres, __u32 *adj_yres) 701{ 702 /* assume full screen (largest size)*/ 703 *adj_xres = scr_xres; 704 *adj_yres = scr_yres; 705 706 /* assume 1:1 pixel ratios if none supplied */ 707 if (!scr_width || !scr_height) { 708 scr_width = scr_xres; 709 scr_height = scr_yres; 710 } 711 712 /* trim to keep aspect ratio */ 713 float x_factor = orig_xres * xpy * scr_height; 714 float y_factor = orig_yres * scr_width; 715 716 /* allow for tolerance so we avoid scaling if framebuffer is standard size */ 717 if (x_factor < y_factor * (1.f - ASPECT_RATIO_TOLERANCE)) 718 *adj_xres = (__u32) (x_factor * *adj_xres / y_factor + 0.5); 719 else if (x_factor * (1.f - ASPECT_RATIO_TOLERANCE) > y_factor) 720 *adj_yres = (__u32) (y_factor * *adj_yres / x_factor + 0.5); 721} 722 723static void set_ext_matrix(omap4_hwc_ext_t *ext, struct hwc_rect region) 724{ 725 int orig_w = WIDTH(region); 726 int orig_h = HEIGHT(region); 727 float xpy = ext->lcd_xpy; 728 729 /* reorientation matrix is: 730 m = (center-from-target-center) * (scale-to-target) * (mirror) * (rotate) * (center-to-original-center) */ 731 732 memcpy(ext->m, m_unit, sizeof(m_unit)); 733 m_translate(ext->m, -(orig_w >> 1) - region.left, -(orig_h >> 1) - region.top); 734 m_rotate(ext->m, ext->current.rotation); 735 if (ext->current.hflip) 736 m_scale(ext->m, 1, -1, 1, 1); 737 738 if (ext->current.rotation & 1) { 739 swap(orig_w, orig_h); 740 xpy = 1. / xpy; 741 } 742 743 /* get target size */ 744 __u32 adj_xres, adj_yres; 745 get_max_dimensions(orig_w, orig_h, xpy, 746 ext->xres, ext->yres, ext->width, ext->height, 747 &adj_xres, &adj_yres); 748 749 m_scale(ext->m, orig_w, adj_xres, orig_h, adj_yres); 750 m_translate(ext->m, ext->xres >> 1, ext->yres >> 1); 751} 752 753static int 754crop_to_rect(struct dss2_ovl_cfg *cfg, struct hwc_rect vis_rect) 755{ 756 struct { 757 int xy[2]; 758 int wh[2]; 759 } crop, win; 760 struct { 761 int lt[2]; 762 int rb[2]; 763 } vis; 764 win.xy[0] = cfg->win.x; win.xy[1] = cfg->win.y; 765 win.wh[0] = cfg->win.w; win.wh[1] = cfg->win.h; 766 crop.xy[0] = cfg->crop.x; crop.xy[1] = cfg->crop.y; 767 crop.wh[0] = cfg->crop.w; crop.wh[1] = cfg->crop.h; 768 vis.lt[0] = vis_rect.left; vis.lt[1] = vis_rect.top; 769 vis.rb[0] = vis_rect.right; vis.rb[1] = vis_rect.bottom; 770 771 int c, swap = cfg->rotation & 1; 772 773 /* align crop window with display coordinates */ 774 if (swap) 775 crop.xy[1] -= (crop.wh[1] = -crop.wh[1]); 776 if (cfg->rotation & 2) 777 crop.xy[!swap] -= (crop.wh[!swap] = -crop.wh[!swap]); 778 if ((!cfg->mirror) ^ !(cfg->rotation & 2)) 779 crop.xy[swap] -= (crop.wh[swap] = -crop.wh[swap]); 780 781 for (c = 0; c < 2; c++) { 782 /* see if complete buffer is outside the vis or it is 783 fully cropped or scaled to 0 */ 784 if (win.wh[c] <= 0 || vis.rb[c] <= vis.lt[c] || 785 win.xy[c] + win.wh[c] <= vis.lt[c] || 786 win.xy[c] >= vis.rb[c] || 787 !crop.wh[c ^ swap]) 788 return -ENOENT; 789 790 /* crop left/top */ 791 if (win.xy[c] < vis.lt[c]) { 792 /* correction term */ 793 int a = (vis.lt[c] - win.xy[c]) * crop.wh[c ^ swap] / win.wh[c]; 794 crop.xy[c ^ swap] += a; 795 crop.wh[c ^ swap] -= a; 796 win.wh[c] -= vis.lt[c] - win.xy[c]; 797 win.xy[c] = vis.lt[c]; 798 } 799 /* crop right/bottom */ 800 if (win.xy[c] + win.wh[c] > vis.rb[c]) { 801 crop.wh[c ^ swap] = crop.wh[c ^ swap] * (vis.rb[c] - win.xy[c]) / win.wh[c]; 802 win.wh[c] = vis.rb[c] - win.xy[c]; 803 } 804 805 if (!crop.wh[c ^ swap] || !win.wh[c]) 806 return -ENOENT; 807 } 808 809 /* realign crop window to buffer coordinates */ 810 if (cfg->rotation & 2) 811 crop.xy[!swap] -= (crop.wh[!swap] = -crop.wh[!swap]); 812 if ((!cfg->mirror) ^ !(cfg->rotation & 2)) 813 crop.xy[swap] -= (crop.wh[swap] = -crop.wh[swap]); 814 if (swap) 815 crop.xy[1] -= (crop.wh[1] = -crop.wh[1]); 816 817 cfg->win.x = win.xy[0]; cfg->win.y = win.xy[1]; 818 cfg->win.w = win.wh[0]; cfg->win.h = win.wh[1]; 819 cfg->crop.x = crop.xy[0]; cfg->crop.y = crop.xy[1]; 820 cfg->crop.w = crop.wh[0]; cfg->crop.h = crop.wh[1]; 821 822 return 0; 823} 824 825static void 826omap4_hwc_apply_transform(float transform[2][3],struct dss2_ovl_cfg *oc) 827{ 828 float x, y, w, h; 829 830 /* display position */ 831 x = transform[0][0] * oc->win.x + transform[0][1] * oc->win.y + transform[0][2]; 832 y = transform[1][0] * oc->win.x + transform[1][1] * oc->win.y + transform[1][2]; 833 w = transform[0][0] * oc->win.w + transform[0][1] * oc->win.h; 834 h = transform[1][0] * oc->win.w + transform[1][1] * oc->win.h; 835 oc->win.x = m_round(w > 0 ? x : x + w); 836 oc->win.y = m_round(h > 0 ? y : y + h); 837 oc->win.w = m_round(w > 0 ? w : -w); 838 oc->win.h = m_round(h > 0 ? h : -h); 839} 840 841static void 842omap4_hwc_adjust_ext_layer(omap4_hwc_ext_t *ext, struct dss2_ovl_info *ovl) 843{ 844 struct dss2_ovl_cfg *oc = &ovl->cfg; 845 846 /* crop to clone region if mirroring */ 847 if (!ext->current.docking && 848 crop_to_rect(&ovl->cfg, ext->mirror_region) != 0) { 849 ovl->cfg.enabled = 0; 850 return; 851 } 852 853 omap4_hwc_apply_transform(ext->m, oc); 854 855 /* combining transformations: F^a*R^b*F^i*R^j = F^(a+b)*R^(j+b*(-1)^i), because F*R = R^(-1)*F */ 856 oc->rotation += (oc->mirror ? -1 : 1) * ext->current.rotation; 857 oc->rotation &= 3; 858 if (ext->current.hflip) 859 oc->mirror = !oc->mirror; 860} 861 862static struct dsscomp_platform_info limits; 863 864static void 865omap4_hwc_adjust_primary_display_layer(omap4_hwc_device_t *hwc_dev, struct dss2_ovl_info *ovl) 866{ 867 struct dss2_ovl_cfg *oc = &ovl->cfg; 868 869 if (crop_to_rect(&ovl->cfg, hwc_dev->primary_region) != 0) { 870 ovl->cfg.enabled = 0; 871 return; 872 } 873 874 omap4_hwc_apply_transform(hwc_dev->primary_m, oc); 875 876 /* combining transformations: F^a*R^b*F^i*R^j = F^(a+b)*R^(j+b*(-1)^i), because F*R = R^(-1)*F */ 877 oc->rotation += (oc->mirror ? -1 : 1) * hwc_dev->primary_rotation; 878 oc->rotation &= 3; 879} 880 881static int omap4_hwc_can_scale(__u32 src_w, __u32 src_h, __u32 dst_w, __u32 dst_h, int is_2d, 882 struct dsscomp_display_info *dis, struct dsscomp_platform_info *limits, 883 __u32 pclk) 884{ 885 __u32 fclk = limits->fclk / 1000; 886 __u32 min_src_w = DIV_ROUND_UP(src_w, is_2d ? limits->max_xdecim_2d : limits->max_xdecim_1d); 887 __u32 min_src_h = DIV_ROUND_UP(src_h, is_2d ? limits->max_ydecim_2d : limits->max_ydecim_1d); 888 889 /* ERRATAs */ 890 /* cannot render 1-width layers on DSI video mode panels - we just disallow all 1-width LCD layers */ 891 if (dis->channel != OMAP_DSS_CHANNEL_DIGIT && dst_w < limits->min_width) 892 return 0; 893 894 /* NOTE: no support for checking YUV422 layers that are tricky to scale */ 895 896 /* FIXME: limit vertical downscale well below theoretical limit as we saw display artifacts */ 897 if (dst_h < src_h / 4) 898 return 0; 899 900 /* max downscale */ 901 if (dst_h * limits->max_downscale < min_src_h) 902 return 0; 903 904 /* for manual panels pclk is 0, and there are no pclk based scaling limits */ 905 if (!pclk) 906 return !(dst_w < src_w / limits->max_downscale / (is_2d ? limits->max_xdecim_2d : limits->max_xdecim_1d)); 907 908 /* :HACK: limit horizontal downscale well below theoretical limit as we saw display artifacts */ 909 if (dst_w * 4 < src_w) 910 return 0; 911 912 /* max horizontal downscale is 4, or the fclk/pixclk */ 913 if (fclk > pclk * limits->max_downscale) 914 fclk = pclk * limits->max_downscale; 915 /* for small parts, we need to use integer fclk/pixclk */ 916 if (src_w < limits->integer_scale_ratio_limit) 917 fclk = fclk / pclk * pclk; 918 if ((__u32) dst_w * fclk < min_src_w * pclk) 919 return 0; 920 921 return 1; 922} 923 924static int omap4_hwc_can_scale_layer(omap4_hwc_device_t *hwc_dev, hwc_layer_1_t *layer, IMG_native_handle_t *handle) 925{ 926 int src_w = WIDTH(layer->sourceCrop); 927 int src_h = HEIGHT(layer->sourceCrop); 928 int dst_w = WIDTH(layer->displayFrame); 929 int dst_h = HEIGHT(layer->displayFrame); 930 931 /* account for 90-degree rotation */ 932 if (layer->transform & HWC_TRANSFORM_ROT_90) 933 swap(src_w, src_h); 934 935 /* NOTE: layers should be able to be scaled externally since 936 framebuffer is able to be scaled on selected external resolution */ 937 return omap4_hwc_can_scale(src_w, src_h, dst_w, dst_h, is_NV12(handle), &hwc_dev->fb_dis, &limits, 938 hwc_dev->fb_dis.timings.pixel_clock); 939} 940 941static int omap4_hwc_is_valid_layer(omap4_hwc_device_t *hwc_dev, 942 hwc_layer_1_t *layer, 943 IMG_native_handle_t *handle) 944{ 945 /* Skip layers are handled by SF */ 946 if ((layer->flags & HWC_SKIP_LAYER) || !handle) 947 return 0; 948 949 if (!omap4_hwc_is_valid_format(handle->iFormat)) 950 return 0; 951 952 /* 1D buffers: no transform, must fit in TILER slot */ 953 if (!is_NV12(handle)) { 954 if (layer->transform) 955 return 0; 956 if (mem1d(handle) > limits.tiler1d_slot_size) 957 return 0; 958 } 959 960 return omap4_hwc_can_scale_layer(hwc_dev, layer, handle); 961} 962 963static __u32 add_scaling_score(__u32 score, 964 __u32 xres, __u32 yres, __u32 refresh, 965 __u32 ext_xres, __u32 ext_yres, 966 __u32 mode_xres, __u32 mode_yres, __u32 mode_refresh) 967{ 968 __u32 area = xres * yres; 969 __u32 ext_area = ext_xres * ext_yres; 970 __u32 mode_area = mode_xres * mode_yres; 971 972 /* prefer to upscale (1% tolerance) [0..1] (insert after 1st bit) */ 973 int upscale = (ext_xres >= xres * 99 / 100 && ext_yres >= yres * 99 / 100); 974 score = (((score & ~1) | upscale) << 1) | (score & 1); 975 976 /* pick minimum scaling [0..16] */ 977 if (ext_area > area) 978 score = (score << 5) | (16 * area / ext_area); 979 else 980 score = (score << 5) | (16 * ext_area / area); 981 982 /* pick smallest leftover area [0..16] */ 983 score = (score << 5) | ((16 * ext_area + (mode_area >> 1)) / mode_area); 984 985 /* adjust mode refresh rate */ 986 mode_refresh += mode_refresh % 6 == 5; 987 988 /* prefer same or higher frame rate */ 989 upscale = (mode_refresh >= refresh); 990 score = (score << 1) | upscale; 991 992 /* pick closest frame rate */ 993 if (mode_refresh > refresh) 994 score = (score << 8) | (240 * refresh / mode_refresh); 995 else 996 score = (score << 8) | (240 * mode_refresh / refresh); 997 998 return score; 999} 1000 1001static int omap4_hwc_set_best_hdmi_mode(omap4_hwc_device_t *hwc_dev, __u32 xres, __u32 yres, 1002 float xpy) 1003{ 1004 int dis_ix = hwc_dev->on_tv ? 0 : 1; 1005 int forced_preferred_mode = 0; 1006 1007 struct _qdis { 1008 struct dsscomp_display_info dis; 1009 struct dsscomp_videomode modedb[32]; 1010 } d = { .dis = { .ix = dis_ix } }; 1011 omap4_hwc_ext_t *ext = &hwc_dev->ext; 1012 1013 d.dis.modedb_len = sizeof(d.modedb) / sizeof(*d.modedb); 1014 int ret = ioctl(hwc_dev->dsscomp_fd, DSSCIOC_QUERY_DISPLAY, &d); 1015 if (ret) 1016 return ret; 1017 1018 if (d.dis.timings.x_res * d.dis.timings.y_res == 0 || 1019 xres * yres == 0) 1020 return -EINVAL; 1021 1022 __u32 i, best = ~0, best_score = 0; 1023 ext->width = d.dis.width_in_mm; 1024 ext->height = d.dis.height_in_mm; 1025 ext->xres = d.dis.timings.x_res; 1026 ext->yres = d.dis.timings.y_res; 1027 1028 /* use VGA external resolution as default */ 1029 if (!ext->xres || !ext->yres) { 1030 ext->xres = 640; 1031 ext->yres = 480; 1032 } 1033 1034 /* 1035 * copy the xres/yres from the preferred mode 1036 */ 1037 __u32 preferred_mode_xres = 0; 1038 __u32 preferred_mode_yres = 0; 1039 1040 char value[PROPERTY_VALUE_MAX]; 1041 if (property_get("persist.hwc.preferred_mode", value, "") <= 0 || 1042 sscanf(value, "%dx%d", &preferred_mode_xres, 1043 &preferred_mode_yres) != 2) { 1044 for (i = 0; i < d.dis.modedb_len; i++) { 1045 if (d.modedb[i].flag & FB_FLAG_PREFERRED) { 1046 preferred_mode_xres = d.modedb[i].xres; 1047 preferred_mode_yres = d.modedb[i].yres; 1048 ALOGD("preferred mode %d: xres %u yres %u\n", 1049 i, d.modedb[i].xres, d.modedb[i].yres); 1050 break; 1051 } 1052 } 1053 } else { 1054 ALOGD("forced preferred mode xres %u yres %u\n", 1055 preferred_mode_xres, preferred_mode_yres); 1056 forced_preferred_mode = 1; 1057 } 1058 1059 __u32 ext_fb_xres, ext_fb_yres; 1060 for (i = 0; i < d.dis.modedb_len; i++) { 1061 __u32 score = 0; 1062 __u32 mode_xres = d.modedb[i].xres; 1063 __u32 mode_yres = d.modedb[i].yres; 1064 __u32 ext_width = d.dis.width_in_mm; 1065 __u32 ext_height = d.dis.height_in_mm; 1066 1067 /* reject it because the hw says it can't actually use this mode */ 1068 if ((d.modedb[i].flag & FB_FLAG_HW_CAPABLE) == 0) 1069 continue; 1070 1071 if (d.modedb[i].vmode & FB_VMODE_INTERLACED) 1072 mode_yres /= 2; 1073 1074 if (d.modedb[i].flag & FB_FLAG_RATIO_4_3) { 1075 ext_width = 4; 1076 ext_height = 3; 1077 } else if (d.modedb[i].flag & FB_FLAG_RATIO_16_9) { 1078 ext_width = 16; 1079 ext_height = 9; 1080 } 1081 1082 if (!mode_xres || !mode_yres) 1083 continue; 1084 1085 get_max_dimensions(xres, yres, xpy, mode_xres, mode_yres, 1086 ext_width, ext_height, &ext_fb_xres, &ext_fb_yres); 1087 1088 /* we need to ensure that even TILER2D buffers can be scaled */ 1089 if (!d.modedb[i].pixclock || 1090 (d.modedb[i].vmode & ~FB_VMODE_INTERLACED) || 1091 !omap4_hwc_can_scale(xres, yres, ext_fb_xres, ext_fb_yres, 1092 1, &d.dis, &limits, 1093 1000000000 / d.modedb[i].pixclock)) 1094 continue; 1095 1096 /* prefer CEA modes */ 1097 if (d.modedb[i].flag & (FB_FLAG_RATIO_4_3 | FB_FLAG_RATIO_16_9)) 1098 score += 1; 1099 1100 /* prefer modes that match the preferred mode's resolution */ 1101 if (d.modedb[i].xres == preferred_mode_xres && 1102 d.modedb[i].yres == preferred_mode_yres) { 1103 if (forced_preferred_mode) 1104 score += 10; 1105 else 1106 score += 1; 1107 } 1108 1109 /* prefer modes the kernel has hinted is the correct mode */ 1110 if (!forced_preferred_mode && (d.modedb[i].flag & FB_FLAG_PREFERRED)) 1111 score += 1; 1112 1113 /* prefer the same mode as we use for mirroring to avoid mode change */ 1114 score = (score << 1) | (i == ~ext->mirror_mode && ext->avoid_mode_change); 1115 1116 score = add_scaling_score(score, xres, yres, 60, ext_fb_xres, ext_fb_yres, 1117 mode_xres, mode_yres, d.modedb[i].refresh ? : 1); 1118 1119 ALOGD("#%d: %dx%d %dHz flag 0x%x vmode 0x%x, score 0x%x", 1120 i, mode_xres, mode_yres, 1121 d.modedb[i].refresh, d.modedb[i].flag, d.modedb[i].vmode, 1122 score); 1123 1124 if (debug) 1125 ALOGD(" score=0x%x adj.res=%dx%d", score, ext_fb_xres, ext_fb_yres); 1126 if (best_score < score) { 1127 ext->width = ext_width; 1128 ext->height = ext_height; 1129 ext->xres = mode_xres; 1130 ext->yres = mode_yres; 1131 best = i; 1132 best_score = score; 1133 } 1134 } 1135 if (~best) { 1136 struct dsscomp_setup_display_data sdis = { .ix = dis_ix, }; 1137 sdis.mode = d.dis.modedb[best]; 1138 ALOGD("picking #%d", best); 1139 /* only reconfigure on change */ 1140 if (ext->last_mode != ~best) { 1141 /* set a property that apps that care (e.g. YouTube) can use 1142 * to determine whether or not to stream lower resolution 1143 * videos when the hdmi mode is < 1080p. 1144 * otherwise, they'd give us 1080p and we'd just scale it 1145 * down to the hdmi mode res. UI apps are always going 1146 * to draw at 1080p and we'll scale down because the 1147 * system can't support dynamic dpi changes. 1148 */ 1149 char display[PROPERTY_VALUE_MAX]; 1150 snprintf(display, sizeof(display), "%dx%d", 1151 d.modedb[best].xres, d.modedb[best].yres); 1152 ALOGD("setting property sys.display-size to %s", display); 1153 property_set("sys.display-size", display); 1154 1155 ioctl(hwc_dev->dsscomp_fd, DSSCIOC_SETUP_DISPLAY, &sdis); 1156 } 1157 ext->last_mode = ~best; 1158 } else { 1159 __u32 ext_width = d.dis.width_in_mm; 1160 __u32 ext_height = d.dis.height_in_mm; 1161 __u32 ext_fb_xres, ext_fb_yres; 1162 1163 get_max_dimensions(xres, yres, xpy, d.dis.timings.x_res, d.dis.timings.y_res, 1164 ext_width, ext_height, &ext_fb_xres, &ext_fb_yres); 1165 if (!d.dis.timings.pixel_clock || 1166 !omap4_hwc_can_scale(xres, yres, ext_fb_xres, ext_fb_yres, 1167 1, &d.dis, &limits, 1168 d.dis.timings.pixel_clock)) { 1169 ALOGW("DSS scaler cannot support HDMI cloning"); 1170 return -1; 1171 } 1172 } 1173 ext->last_xres_used = xres; 1174 ext->last_yres_used = yres; 1175 ext->last_xpy = xpy; 1176 if (d.dis.channel == OMAP_DSS_CHANNEL_DIGIT) 1177 ext->on_tv = 1; 1178 return 0; 1179} 1180 1181static void gather_layer_statistics(omap4_hwc_device_t *hwc_dev, struct counts *num, hwc_display_contents_1_t *list) 1182{ 1183 unsigned int i; 1184 1185 /* Figure out how many layers we can support via DSS */ 1186 for (i = 0; list && i < list->numHwLayers; i++) { 1187 hwc_layer_1_t *layer = &list->hwLayers[i]; 1188 IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; 1189 1190 layer->compositionType = HWC_FRAMEBUFFER; 1191 1192 if (omap4_hwc_is_valid_layer(hwc_dev, layer, handle)) { 1193 num->possible_overlay_layers++; 1194 1195 /* NV12 layers can only be rendered on scaling overlays */ 1196 if (scaled(layer) || is_NV12(handle) || hwc_dev->primary_transform) 1197 num->scaled_layers++; 1198 1199 if (is_BGR(handle)) 1200 num->BGR++; 1201 else if (is_RGB(handle)) 1202 num->RGB++; 1203 else if (is_NV12(handle)) 1204 num->NV12++; 1205 1206 if (dockable(layer)) 1207 num->dockable++; 1208 1209 if (is_protected(layer)) 1210 num->protected++; 1211 1212 num->mem += mem1d(handle); 1213 } 1214 } 1215 hwc_dev->stats = *num; 1216} 1217 1218static void decide_supported_cloning(omap4_hwc_device_t *hwc_dev, struct counts *num) 1219{ 1220 omap4_hwc_ext_t *ext = &hwc_dev->ext; 1221 int nonscaling_ovls = NUM_NONSCALING_OVERLAYS; 1222 num->max_hw_overlays = MAX_HW_OVERLAYS; 1223 1224 /* 1225 * We cannot atomically switch overlays from one display to another. First, they 1226 * have to be disabled, and the disabling has to take effect on the current display. 1227 * We keep track of the available number of overlays here. 1228 */ 1229 if (ext->dock.enabled && !(ext->mirror.enabled && !(num->dockable || ext->force_dock))) { 1230 /* some overlays may already be used by the external display, so we account for this */ 1231 1232 /* reserve just a video pipeline for HDMI if docking */ 1233 hwc_dev->ext_ovls = (num->dockable || ext->force_dock) ? 1 : 0; 1234 num->max_hw_overlays -= max(hwc_dev->ext_ovls, hwc_dev->last_ext_ovls); 1235 1236 /* use mirroring transform if we are auto-switching to docking mode while mirroring*/ 1237 if (ext->mirror.enabled) { 1238 ext->current = ext->mirror; 1239 ext->current.docking = 1; 1240 } else { 1241 ext->current = ext->dock; 1242 } 1243 } else if (ext->mirror.enabled) { 1244 /* 1245 * otherwise, manage just from half the pipelines. NOTE: there is 1246 * no danger of having used too many overlays for external display here. 1247 */ 1248 1249 num->max_hw_overlays >>= 1; 1250 nonscaling_ovls >>= 1; 1251 hwc_dev->ext_ovls = MAX_HW_OVERLAYS - num->max_hw_overlays; 1252 ext->current = ext->mirror; 1253 } else { 1254 num->max_hw_overlays -= hwc_dev->last_ext_ovls; 1255 hwc_dev->ext_ovls = 0; 1256 ext->current.enabled = 0; 1257 } 1258 1259 /* 1260 * :TRICKY: We may not have enough overlays on the external display. We "reserve" them 1261 * here to figure out if mirroring is supported, but may not do mirroring for the first 1262 * frame while the overlays required for it are cleared. 1263 */ 1264 hwc_dev->ext_ovls_wanted = hwc_dev->ext_ovls; 1265 hwc_dev->ext_ovls = min(MAX_HW_OVERLAYS - hwc_dev->last_int_ovls, hwc_dev->ext_ovls); 1266 1267 /* if mirroring, we are limited by both internal and external overlays. However, 1268 ext_ovls is always <= MAX_HW_OVERLAYS / 2 <= max_hw_overlays */ 1269 if (!num->protected && hwc_dev->ext_ovls && ext->current.enabled && !ext->current.docking) 1270 num->max_hw_overlays = hwc_dev->ext_ovls; 1271 1272 /* If FB is not same resolution as LCD don't use GFX pipe line*/ 1273 if (hwc_dev->primary_transform) { 1274 num->max_hw_overlays -= NUM_NONSCALING_OVERLAYS; 1275 num->max_scaling_overlays = num->max_hw_overlays; 1276 } else 1277 num->max_scaling_overlays = num->max_hw_overlays - nonscaling_ovls; 1278} 1279 1280static int can_dss_render_all(omap4_hwc_device_t *hwc_dev, struct counts *num) 1281{ 1282 omap4_hwc_ext_t *ext = &hwc_dev->ext; 1283 int on_tv = hwc_dev->on_tv || (ext->on_tv && ext->current.enabled); 1284 int tform = ext->current.enabled && (ext->current.rotation || ext->current.hflip); 1285 1286 return !hwc_dev->force_sgx && 1287 /* must have at least one layer if using composition bypass to get sync object */ 1288 num->possible_overlay_layers && 1289 num->possible_overlay_layers <= num->max_hw_overlays && 1290 num->possible_overlay_layers == num->composited_layers && 1291 num->scaled_layers <= num->max_scaling_overlays && 1292 num->NV12 <= num->max_scaling_overlays && 1293 /* fits into TILER slot */ 1294 num->mem <= limits.tiler1d_slot_size && 1295 /* we cannot clone non-NV12 transformed layers */ 1296 (!tform || (num->NV12 == num->possible_overlay_layers) || 1297 (num->NV12 && ext->current.docking)) && 1298 /* HDMI cannot display BGR */ 1299 (num->BGR == 0 || (num->RGB == 0 && !on_tv) || !hwc_dev->flags_rgb_order); 1300} 1301 1302static inline int can_dss_render_layer(omap4_hwc_device_t *hwc_dev, 1303 hwc_layer_1_t *layer) 1304{ 1305 IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; 1306 1307 omap4_hwc_ext_t *ext = &hwc_dev->ext; 1308 int cloning = ext->current.enabled && (!ext->current.docking || (handle!=NULL ? dockable(layer) : 0)); 1309 int on_tv = hwc_dev->on_tv || (ext->on_tv && cloning); 1310 int tform = cloning && (ext->current.rotation || ext->current.hflip); 1311 1312 return omap4_hwc_is_valid_layer(hwc_dev, layer, handle) && 1313 /* cannot rotate non-NV12 layers on external display */ 1314 (!tform || is_NV12(handle)) && 1315 /* skip non-NV12 layers if also using SGX (if nv12_only flag is set) */ 1316 (!hwc_dev->flags_nv12_only || (!hwc_dev->use_sgx || is_NV12(handle))) && 1317 /* make sure RGB ordering is consistent (if rgb_order flag is set) */ 1318 (!(hwc_dev->swap_rb ? is_RGB(handle) : is_BGR(handle)) || 1319 !hwc_dev->flags_rgb_order) && 1320 /* TV can only render RGB */ 1321 !(on_tv && is_BGR(handle)); 1322} 1323 1324static inline int display_area(struct dss2_ovl_info *o) 1325{ 1326 return o->cfg.win.w * o->cfg.win.h; 1327} 1328 1329static int clone_layer(omap4_hwc_device_t *hwc_dev, int ix) { 1330 struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->comp_data.dsscomp_data; 1331 omap4_hwc_ext_t *ext = &hwc_dev->ext; 1332 int ext_ovl_ix = dsscomp->num_ovls - hwc_dev->post2_layers; 1333 struct dss2_ovl_info *o = &dsscomp->ovls[dsscomp->num_ovls]; 1334 1335 if (dsscomp->num_ovls >= MAX_HW_OVERLAYS) { 1336 ALOGE("**** cannot clone layer #%d. using all %d overlays.", ix, dsscomp->num_ovls); 1337 return -EBUSY; 1338 } 1339 1340 memcpy(o, dsscomp->ovls + ix, sizeof(*o)); 1341 1342 /* reserve overlays at end for other display */ 1343 o->cfg.ix = MAX_HW_OVERLAYS - 1 - ext_ovl_ix; 1344 o->cfg.mgr_ix = 1; 1345 /* 1346 * Here the assumption is that overlay0 is the one attached to FB. 1347 * Hence this clone_layer call is for FB cloning (provided use_sgx is true). 1348 */ 1349 /* For the external displays whose transform is the same as 1350 * that of primary display, ion_handles would be NULL hence 1351 * the below logic doesn't execute. 1352 */ 1353 if (ix == 0 && hwc_dev->ion_handles[sync_id%2] && hwc_dev->use_sgx) { 1354 o->addressing = OMAP_DSS_BUFADDR_ION; 1355 o->ba = (int)hwc_dev->ion_handles[sync_id%2]; 1356 } else { 1357 o->addressing = OMAP_DSS_BUFADDR_OVL_IX; 1358 o->ba = ix; 1359 } 1360 1361 /* use distinct z values (to simplify z-order checking) */ 1362 o->cfg.zorder += hwc_dev->post2_layers; 1363 1364 omap4_hwc_adjust_ext_layer(&hwc_dev->ext, o); 1365 dsscomp->num_ovls++; 1366 return 0; 1367} 1368 1369static int clone_external_layer(omap4_hwc_device_t *hwc_dev, int ix) { 1370 struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->comp_data.dsscomp_data; 1371 omap4_hwc_ext_t *ext = &hwc_dev->ext; 1372 1373 /* mirror only 1 external layer */ 1374 struct dss2_ovl_info *o = &dsscomp->ovls[ix]; 1375 1376 /* full screen video after transformation */ 1377 __u32 xres = o->cfg.crop.w, yres = o->cfg.crop.h; 1378 if ((ext->current.rotation + o->cfg.rotation) & 1) 1379 swap(xres, yres); 1380 float xpy = ext->lcd_xpy * o->cfg.win.w / o->cfg.win.h; 1381 if (o->cfg.rotation & 1) 1382 xpy = o->cfg.crop.h / xpy / o->cfg.crop.w; 1383 else 1384 xpy = o->cfg.crop.h * xpy / o->cfg.crop.w; 1385 if (ext->current.rotation & 1) 1386 xpy = 1. / xpy; 1387 1388 /* adjust hdmi mode based on resolution */ 1389 if (xres != ext->last_xres_used || 1390 yres != ext->last_yres_used || 1391 xpy < ext->last_xpy * (1.f - ASPECT_RATIO_TOLERANCE) || 1392 xpy * (1.f - ASPECT_RATIO_TOLERANCE) > ext->last_xpy) { 1393 ALOGD("set up HDMI for %d*%d\n", xres, yres); 1394 if (omap4_hwc_set_best_hdmi_mode(hwc_dev, xres, yres, xpy)) { 1395 ext->current.enabled = 0; 1396 return -ENODEV; 1397 } 1398 } 1399 1400 struct hwc_rect region = { 1401 .left = o->cfg.win.x, .top = o->cfg.win.y, 1402 .right = o->cfg.win.x + o->cfg.win.w, 1403 .bottom = o->cfg.win.y + o->cfg.win.h 1404 }; 1405 set_ext_matrix(&hwc_dev->ext, region); 1406 1407 return clone_layer(hwc_dev, ix); 1408} 1409 1410static int setup_mirroring(omap4_hwc_device_t *hwc_dev) 1411{ 1412 omap4_hwc_ext_t *ext = &hwc_dev->ext; 1413 1414 __u32 xres = WIDTH(ext->mirror_region); 1415 __u32 yres = HEIGHT(ext->mirror_region); 1416 if (ext->current.rotation & 1) 1417 swap(xres, yres); 1418 if (omap4_hwc_set_best_hdmi_mode(hwc_dev, xres, yres, ext->lcd_xpy)) 1419 return -ENODEV; 1420 set_ext_matrix(ext, ext->mirror_region); 1421 return 0; 1422} 1423 1424/* 1425 * We're using "implicit" synchronization, so make sure we aren't passing any 1426 * sync object descriptors around. 1427 */ 1428static void check_sync_fds(size_t numDisplays, hwc_display_contents_1_t** displays) 1429{ 1430 //ALOGD("checking sync FDs"); 1431 unsigned int i, j; 1432 for (i = 0; i < numDisplays; i++) { 1433 hwc_display_contents_1_t* list = displays[i]; 1434 if (list->retireFenceFd >= 0) { 1435 ALOGW("retireFenceFd[%u] was %d", i, list->retireFenceFd); 1436 list->retireFenceFd = -1; 1437 } 1438 1439 for (j = 0; j < list->numHwLayers; j++) { 1440 hwc_layer_1_t* layer = &list->hwLayers[j]; 1441 if (layer->acquireFenceFd >= 0) { 1442 ALOGW("acquireFenceFd[%u][%u] was %d, closing", i, j, layer->acquireFenceFd); 1443 close(layer->acquireFenceFd); 1444 layer->acquireFenceFd = -1; 1445 } 1446 if (layer->releaseFenceFd >= 0) { 1447 ALOGW("releaseFenceFd[%u][%u] was %d", i, j, layer->releaseFenceFd); 1448 layer->releaseFenceFd = -1; 1449 } 1450 } 1451 } 1452} 1453 1454/* test if layer appears to be RGB32 (4 Bpp) and > 1280x720 */ 1455static int is_large_rgb32_layer(const hwc_layer_1_t *layer) 1456{ 1457 IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; 1458 1459 return is_RGB32(handle) && 1460 (((layer->sourceCrop.right - layer->sourceCrop.left) > 1280) || 1461 ((layer->sourceCrop.bottom - layer->sourceCrop.top) > 720)); 1462} 1463 1464static void blit_reset(omap4_hwc_device_t *hwc_dev, int flags) 1465{ 1466 hwc_dev->blit_flags = 0; 1467 hwc_dev->blit_num = 0; 1468 hwc_dev->post2_blit_buffers = 0; 1469 hwc_dev->comp_data.blit_data.rgz_items = 0; 1470 1471 /* We want to maintain the rgz dirty region data if there are no geometry changes */ 1472 if (flags & HWC_GEOMETRY_CHANGED) 1473 rgz_release(&grgz); 1474} 1475 1476static int blit_layers(omap4_hwc_device_t *hwc_dev, hwc_layer_list_t *list, int bufoff) 1477{ 1478 /* Do not blit if this frame will be composed entirely by the GPU */ 1479 if (!list || hwc_dev->force_sgx) 1480 goto err_out; 1481 1482 int rgz_in_op; 1483 int rgz_out_op; 1484 1485 switch (hwc_dev->blt_mode) { 1486 case BLTMODE_PAINT: 1487 rgz_in_op = RGZ_IN_HWCCHK; 1488 rgz_out_op = RGZ_OUT_BVCMD_PAINT; 1489 break; 1490 case BLTMODE_REGION: 1491 default: 1492 rgz_in_op = RGZ_IN_HWC; 1493 rgz_out_op = RGZ_OUT_BVCMD_REGION; 1494 break; 1495 } 1496 1497 rgz_in_params_t in = { 1498 .op = rgz_in_op, 1499 .data = { 1500 .hwc = { 1501 .dstgeom = &gscrngeom, 1502 .layers = list->hwLayers, 1503 .layerno = list->numHwLayers 1504 } 1505 } 1506 }; 1507 1508 /* 1509 * This means if all the layers marked for the FRAMEBUFFER cannot be 1510 * blitted, do not blit, for e.g. SKIP layers 1511 */ 1512 if (rgz_in(&in, &grgz) != RGZ_ALL) 1513 goto err_out; 1514 1515 unsigned int i, count = 0; 1516 for (i = 0; i < list->numHwLayers; i++) { 1517 if (list->hwLayers[i].compositionType != HWC_OVERLAY) { 1518 count++; 1519 } 1520 } 1521 1522 rgz_out_params_t out = { 1523 .op = rgz_out_op, 1524 .data = { 1525 .bvc = { 1526 .dstgeom = &gscrngeom, 1527 .noblend = 0, 1528 } 1529 } 1530 }; 1531 1532 if (rgz_out(&grgz, &out) != 0) { 1533 ALOGE("Failed generating blits"); 1534 goto err_out; 1535 } 1536 1537 /* This is a special situation where the regionizer decided no blits are 1538 * needed for this frame but there are blit buffers to synchronize with. Can 1539 * happen only if the regionizer is enabled otherwise it's likely a bug 1540 */ 1541 if (rgz_out_op != RGZ_OUT_BVCMD_REGION && out.data.bvc.out_blits == 0 && out.data.bvc.out_nhndls > 0) { 1542 ALOGE("Regionizer invalid output blit_num %d, post2_blit_buffers %d", out.data.bvc.out_blits, out.data.bvc.out_nhndls); 1543 goto err_out; 1544 } 1545 1546 hwc_dev->blit_flags |= HWC_BLT_FLAG_USE_FB; 1547 hwc_dev->blit_num = out.data.bvc.out_blits; 1548 hwc_dev->post2_blit_buffers = out.data.bvc.out_nhndls; 1549 for (i = 0; i < hwc_dev->post2_blit_buffers; i++) { 1550 //ALOGI("blit buffers[%d] = %p", bufoff, out.data.bvc.out_hndls[i]); 1551 hwc_dev->buffers[bufoff++] = out.data.bvc.out_hndls[i]; 1552 } 1553 1554 struct rgz_blt_entry *res_blit_ops = (struct rgz_blt_entry *) out.data.bvc.cmdp; 1555 memcpy(hwc_dev->comp_data.blit_data.rgz_blts, res_blit_ops, sizeof(*res_blit_ops) * out.data.bvc.cmdlen); 1556 ALOGI_IF(debugblt, "blt struct sz %d", sizeof(*res_blit_ops) * out.data.bvc.cmdlen); 1557 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); 1558 1559 /* all layers will be rendered without SGX help either via DSS or blitter */ 1560 for (i = 0; i < list->numHwLayers; i++) { 1561 if (list->hwLayers[i].compositionType != HWC_OVERLAY) { 1562 list->hwLayers[i].compositionType = HWC_OVERLAY; 1563 //ALOGI("blitting layer %d", i); 1564 list->hwLayers[i].hints &= ~HWC_HINT_TRIPLE_BUFFER; 1565 } 1566 list->hwLayers[i].hints &= ~HWC_HINT_CLEAR_FB; 1567 } 1568 return 1; 1569 1570err_out: 1571 rgz_release(&grgz); 1572 return 0; 1573} 1574 1575void debug_post2(omap4_hwc_device_t *hwc_dev, int nbufs) 1576{ 1577 if (!debugpost2) 1578 return; 1579 struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->comp_data.dsscomp_data; 1580 int i; 1581 for (i=0; i<nbufs; i++) { 1582 ALOGI("buf[%d] hndl %p", i, hwc_dev->buffers[i]); 1583 } 1584 for (i=0; i < dsscomp->num_ovls; i++) { 1585 ALOGI("ovl[%d] ba %d", i, dsscomp->ovls[i].ba); 1586 } 1587} 1588 1589static int free_tiler2d_buffers(omap4_hwc_device_t *hwc_dev) 1590{ 1591 int i; 1592 1593 for (i = 0 ; i < NUM_EXT_DISPLAY_BACK_BUFFERS; i++) { 1594 ion_free(hwc_dev->ion_fd, hwc_dev->ion_handles[i]); 1595 hwc_dev->ion_handles[i] = NULL; 1596 } 1597 return 0; 1598} 1599 1600static int allocate_tiler2d_buffers(omap4_hwc_device_t *hwc_dev) 1601{ 1602 int ret, i; 1603 size_t stride; 1604 1605 if (hwc_dev->ion_fd < 0) { 1606 ALOGE("No ion fd, hence can't allocate tiler2d buffers"); 1607 return -1; 1608 } 1609 1610 for (i = 0; i < NUM_EXT_DISPLAY_BACK_BUFFERS; i++) { 1611 if (hwc_dev->ion_handles[i]) 1612 return 0; 1613 } 1614 1615 for (i = 0 ; i < NUM_EXT_DISPLAY_BACK_BUFFERS; i++) { 1616 ret = ion_alloc_tiler(hwc_dev->ion_fd, hwc_dev->fb_dev->base.width, hwc_dev->fb_dev->base.height, 1617 TILER_PIXEL_FMT_32BIT, 0, &hwc_dev->ion_handles[i], &stride); 1618 if (ret) 1619 goto handle_error; 1620 1621 ALOGI("ion handle[%d][%p]", i, hwc_dev->ion_handles[i]); 1622 } 1623 return 0; 1624 1625handle_error: 1626 free_tiler2d_buffers(hwc_dev); 1627 return -1; 1628} 1629 1630static int omap4_hwc_prepare(struct hwc_composer_device_1 *dev, size_t numDisplays, 1631 hwc_display_contents_1_t** displays) 1632{ 1633 if (!numDisplays || displays == NULL) { 1634 return 0; 1635 } 1636 1637 hwc_display_contents_1_t* list = displays[0]; // ignore displays beyond the first 1638 omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev; 1639 struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->comp_data.dsscomp_data; 1640 struct counts num = { .composited_layers = list ? list->numHwLayers : 0 }; 1641 unsigned int i, ix; 1642 1643 pthread_mutex_lock(&hwc_dev->lock); 1644 memset(dsscomp, 0x0, sizeof(*dsscomp)); 1645 dsscomp->sync_id = sync_id++; 1646 1647 gather_layer_statistics(hwc_dev, &num, list); 1648 1649 decide_supported_cloning(hwc_dev, &num); 1650 1651 /* Disable the forced SGX rendering if there is only one layer */ 1652 if (hwc_dev->force_sgx && num.composited_layers <= 1) 1653 hwc_dev->force_sgx = 0; 1654 1655 /* phase 3 logic */ 1656 if (can_dss_render_all(hwc_dev, &num)) { 1657 /* All layers can be handled by the DSS -- don't use SGX for composition */ 1658 hwc_dev->use_sgx = 0; 1659 hwc_dev->swap_rb = num.BGR != 0; 1660 } else { 1661 /* Use SGX for composition plus first 3 layers that are DSS renderable */ 1662 hwc_dev->use_sgx = 1; 1663 hwc_dev->swap_rb = is_BGR_format(hwc_dev->fb_dev->base.format); 1664 } 1665 1666 /* setup pipes */ 1667 int z = 0; 1668 int fb_z = -1; 1669 int scaled_gfx = 0; 1670 int ix_docking = -1; 1671 int big_layers = 0; 1672 1673 int blit_all = 0; 1674 blit_reset(hwc_dev, list ? list->flags : 0); 1675 1676 /* If the SGX is used or we are going to blit something we need a framebuffer 1677 * and a DSS pipe 1678 */ 1679 int needs_fb = hwc_dev->use_sgx; 1680 1681 if (hwc_dev->blt_policy == BLTPOLICY_ALL) { 1682 /* Check if we can blit everything */ 1683 blit_all = blit_layers(hwc_dev, list, 0); 1684 if (blit_all) { 1685 needs_fb = 1; 1686 hwc_dev->use_sgx = 0; 1687 } 1688 } 1689 1690 /* If a framebuffer is needed, begin using VID1 for DSS overlay layers, 1691 * we need GFX for FB 1692 */ 1693 dsscomp->num_ovls = needs_fb ? 1 /*VID1*/ : 0 /*GFX*/; 1694 1695 /* set up if DSS layers */ 1696 unsigned int mem_used = 0; 1697 for (i = 0; list && i < list->numHwLayers && !blit_all; i++) { 1698 hwc_layer_1_t *layer = &list->hwLayers[i]; 1699 IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; 1700 1701 if (dsscomp->num_ovls < num.max_hw_overlays && 1702 can_dss_render_layer(hwc_dev, layer) && 1703 (!hwc_dev->force_sgx || 1704 /* render protected and dockable layers via DSS */ 1705 is_protected(layer) || 1706 is_upscaled_NV12(hwc_dev, layer) || 1707 (hwc_dev->ext.current.docking && hwc_dev->ext.current.enabled && dockable(layer))) && 1708 mem_used + mem1d(handle) < limits.tiler1d_slot_size && 1709 /* can't have a transparent overlay in the middle of the framebuffer stack */ 1710 !(is_BLENDED(layer) && fb_z >= 0) && 1711 /* current hardware is unable to keep up with more than 1 'large' RGB32 layer */ 1712 !(is_large_rgb32_layer(layer) && big_layers > 0)) { 1713 1714 /* render via DSS overlay */ 1715 mem_used += mem1d(handle); 1716 layer->compositionType = HWC_OVERLAY; 1717 /* 1718 * This hint will not be used in vanilla ICS, but maybe in 1719 * JellyBean, it is useful to distinguish between blts and true 1720 * overlays 1721 */ 1722 layer->hints |= HWC_HINT_TRIPLE_BUFFER; 1723 1724 /* clear FB above all opaque layers if rendering via SGX */ 1725 if (hwc_dev->use_sgx && !is_BLENDED(layer)) 1726 layer->hints |= HWC_HINT_CLEAR_FB; 1727 1728 hwc_dev->buffers[dsscomp->num_ovls] = layer->handle; 1729 1730 omap4_hwc_setup_layer(hwc_dev, 1731 &dsscomp->ovls[dsscomp->num_ovls], 1732 layer, 1733 z, 1734 handle->iFormat, 1735 handle->iWidth, 1736 handle->iHeight); 1737 1738 dsscomp->ovls[dsscomp->num_ovls].cfg.ix = dsscomp->num_ovls + hwc_dev->primary_transform; 1739 dsscomp->ovls[dsscomp->num_ovls].addressing = OMAP_DSS_BUFADDR_LAYER_IX; 1740 dsscomp->ovls[dsscomp->num_ovls].ba = dsscomp->num_ovls; 1741 1742 /* ensure GFX layer is never scaled */ 1743 if ((dsscomp->num_ovls == 0) && (!hwc_dev->primary_transform)) { 1744 scaled_gfx = scaled(layer) || is_NV12(handle); 1745 } else if (scaled_gfx && !scaled(layer) && !is_NV12(handle)) { 1746 /* swap GFX layer with this one */ 1747 dsscomp->ovls[dsscomp->num_ovls].cfg.ix = 0; 1748 dsscomp->ovls[0].cfg.ix = dsscomp->num_ovls; 1749 scaled_gfx = 0; 1750 } 1751 1752 /* remember largest dockable layer */ 1753 if (dockable(layer) && 1754 (ix_docking < 0 || 1755 display_area(&dsscomp->ovls[dsscomp->num_ovls]) > display_area(&dsscomp->ovls[ix_docking]))) 1756 ix_docking = dsscomp->num_ovls; 1757 1758 dsscomp->num_ovls++; 1759 z++; 1760 1761 /* record whether or not this was a 'big' RGB32 layer */ 1762 if (is_large_rgb32_layer(layer)) { 1763 big_layers++; 1764 } 1765 } else if (hwc_dev->use_sgx) { 1766 if (fb_z < 0) { 1767 /* NOTE: we are not handling transparent cutout for now */ 1768 fb_z = z; 1769 z++; 1770 } else { 1771 /* move fb z-order up (by lowering dss layers) */ 1772 while (fb_z < z - 1) 1773 dsscomp->ovls[1 + fb_z++].cfg.zorder--; 1774 } 1775 } 1776 } 1777 1778 /* if scaling GFX (e.g. only 1 scaled surface) use a VID pipe */ 1779 if (scaled_gfx) 1780 dsscomp->ovls[0].cfg.ix = dsscomp->num_ovls; 1781 1782 if (hwc_dev->blt_policy == BLTPOLICY_DEFAULT) { 1783 if (hwc_dev->use_sgx) { 1784 if (blit_layers(hwc_dev, list, dsscomp->num_ovls == 1 ? 0 : dsscomp->num_ovls)) { 1785 hwc_dev->use_sgx = 0; 1786 } 1787 } 1788 } 1789 1790 /* If the SGX is not used and there is blit data we need a framebuffer and 1791 * a DSS pipe well configured for it 1792 */ 1793 if (needs_fb) { 1794 /* assign a z-layer for fb */ 1795 if (fb_z < 0) { 1796 if (!hwc_dev->blt_policy != BLTPOLICY_DISABLED && num.composited_layers) 1797 ALOGE("**** should have assigned z-layer for fb"); 1798 fb_z = z++; 1799 } 1800 /* 1801 * This is needed because if we blit all we would lose the handle of 1802 * the first layer 1803 */ 1804 if (hwc_dev->blit_num == 0) { 1805 hwc_dev->buffers[0] = NULL; 1806 } 1807 omap4_hwc_setup_layer_base(&dsscomp->ovls[0].cfg, fb_z, 1808 hwc_dev->fb_dev->base.format, 1809 1, /* FB is always premultiplied */ 1810 hwc_dev->fb_dev->base.width, 1811 hwc_dev->fb_dev->base.height); 1812 dsscomp->ovls[0].cfg.pre_mult_alpha = 1; 1813 dsscomp->ovls[0].addressing = OMAP_DSS_BUFADDR_LAYER_IX; 1814 dsscomp->ovls[0].ba = 0; 1815 dsscomp->ovls[0].cfg.ix = hwc_dev->primary_transform; 1816 } 1817 1818 /* mirror layers */ 1819 hwc_dev->post2_layers = dsscomp->num_ovls; 1820 1821 omap4_hwc_ext_t *ext = &hwc_dev->ext; 1822 if (ext->current.enabled && hwc_dev->ext_ovls) { 1823 if (ext->current.docking && ix_docking >= 0) { 1824 if (clone_external_layer(hwc_dev, ix_docking) == 0) 1825 dsscomp->ovls[dsscomp->num_ovls - 1].cfg.zorder = z++; 1826 } else if (ext->current.docking && ix_docking < 0 && ext->force_dock) { 1827 ix_docking = dsscomp->num_ovls; 1828 struct dss2_ovl_info *oi = &dsscomp->ovls[ix_docking]; 1829 omap4_hwc_setup_layer_base(&oi->cfg, 0, HAL_PIXEL_FORMAT_BGRA_8888, 1, 1830 dock_image.width, dock_image.height); 1831 oi->cfg.stride = dock_image.rowbytes; 1832 if (clone_external_layer(hwc_dev, ix_docking) == 0) { 1833 oi->addressing = OMAP_DSS_BUFADDR_FB; 1834 oi->ba = 0; 1835 z++; 1836 } 1837 } else if (!ext->current.docking) { 1838 int res = 0; 1839 1840 /* reset mode if we are coming from docking */ 1841 if (ext->last.docking) 1842 res = setup_mirroring(hwc_dev); 1843 1844 /* mirror all layers */ 1845 for (ix = 0; res == 0 && ix < hwc_dev->post2_layers; ix++) { 1846 if (clone_layer(hwc_dev, ix)) 1847 break; 1848 z++; 1849 } 1850 } 1851 } 1852 1853 /* Apply transform for primary display */ 1854 if (hwc_dev->primary_transform) 1855 for (i = 0; i < dsscomp->num_ovls; i++) { 1856 if(dsscomp->ovls[i].cfg.mgr_ix == 0) 1857 omap4_hwc_adjust_primary_display_layer(hwc_dev, &dsscomp->ovls[i]); 1858 } 1859 1860 ext->last = ext->current; 1861 1862 if (z != dsscomp->num_ovls || dsscomp->num_ovls > MAX_HW_OVERLAYS) 1863 ALOGE("**** used %d z-layers for %d overlays\n", z, dsscomp->num_ovls); 1864 1865 /* verify all z-orders and overlay indices are distinct */ 1866 for (i = z = ix = 0; i < dsscomp->num_ovls; i++) { 1867 struct dss2_ovl_cfg *c = &dsscomp->ovls[i].cfg; 1868 1869 if (z & (1 << c->zorder)) 1870 ALOGE("**** used z-order #%d multiple times", c->zorder); 1871 if (ix & (1 << c->ix)) 1872 ALOGE("**** used ovl index #%d multiple times", c->ix); 1873 z |= 1 << c->zorder; 1874 ix |= 1 << c->ix; 1875 } 1876 dsscomp->mode = DSSCOMP_SETUP_DISPLAY; 1877 dsscomp->mgrs[0].ix = 0; 1878 dsscomp->mgrs[0].alpha_blending = 1; 1879 dsscomp->mgrs[0].swap_rb = hwc_dev->swap_rb; 1880 dsscomp->num_mgrs = 1; 1881 1882 if (ext->current.enabled || hwc_dev->last_ext_ovls) { 1883 dsscomp->mgrs[1] = dsscomp->mgrs[0]; 1884 dsscomp->mgrs[1].ix = 1; 1885 dsscomp->num_mgrs++; 1886 hwc_dev->ext_ovls = dsscomp->num_ovls - hwc_dev->post2_layers; 1887 } 1888 1889 if (debug) { 1890 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", 1891 dsscomp->sync_id, 1892 hwc_dev->use_sgx ? "SGX+OVL" : "all-OVL", 1893 num.composited_layers, 1894 num.possible_overlay_layers, num.scaled_layers, 1895 num.RGB, num.BGR, num.NV12, 1896 ext->on_tv ? "tv+" : "", 1897 ext->current.enabled ? ext->current.docking ? "dock+" : "mirror+" : "OFF+", 1898 ext->current.rotation * 90, 1899 ext->current.hflip ? "+hflip" : "", 1900 hwc_dev->ext_ovls, num.max_hw_overlays, hwc_dev->last_ext_ovls, hwc_dev->last_int_ovls); 1901 } 1902 1903 pthread_mutex_unlock(&hwc_dev->lock); 1904 return 0; 1905} 1906 1907static void omap4_hwc_reset_screen(omap4_hwc_device_t *hwc_dev) 1908{ 1909 static int first_set = 1; 1910 int ret; 1911 1912 if (first_set) { 1913 first_set = 0; 1914 struct dsscomp_setup_dispc_data d = { 1915 .num_mgrs = 1, 1916 }; 1917 /* remove bootloader image from the screen as blank/unblank does not change the composition */ 1918 ret = ioctl(hwc_dev->dsscomp_fd, DSSCIOC_SETUP_DISPC, &d); 1919 if (ret) 1920 ALOGW("failed to remove bootloader image"); 1921 1922 /* blank and unblank fd to make sure display is properly programmed on boot. 1923 * This is needed because the bootloader can not be trusted. 1924 */ 1925 ret = ioctl(hwc_dev->fb_fd, FBIOBLANK, FB_BLANK_POWERDOWN); 1926 if (ret) 1927 ALOGW("failed to blank display"); 1928 1929 ret = ioctl(hwc_dev->fb_fd, FBIOBLANK, FB_BLANK_UNBLANK); 1930 if (ret) 1931 ALOGW("failed to blank display"); 1932 } 1933} 1934 1935static int omap4_hwc_set(struct hwc_composer_device_1 *dev, 1936 size_t numDisplays, hwc_display_contents_1_t** displays) 1937{ 1938 if (!numDisplays || displays == NULL) { 1939 ALOGD("set: empty display list"); 1940 return 0; 1941 } 1942 hwc_display_t dpy = NULL; 1943 hwc_surface_t sur = NULL; 1944 hwc_display_contents_1_t* list = displays[0]; // ignore displays beyond the first 1945 if (list != NULL) { 1946 dpy = list->dpy; 1947 sur = list->sur; 1948 } 1949 omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev; 1950 struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->comp_data.dsscomp_data; 1951 int err = 0; 1952 int invalidate; 1953 1954 pthread_mutex_lock(&hwc_dev->lock); 1955 1956 /* disable resetting the screen on the first boot for devices 1957 * with hdmi as primary input. 1958 */ 1959 if (!hwc_dev->on_tv) 1960 omap4_hwc_reset_screen(hwc_dev); 1961 1962 invalidate = hwc_dev->ext_ovls_wanted && (hwc_dev->ext_ovls < hwc_dev->ext_ovls_wanted) && 1963 (hwc_dev->stats.protected || !hwc_dev->ext_ovls); 1964 1965 if (debug) 1966 dump_set_info(hwc_dev, list); 1967 1968 if (dpy && sur) { 1969 // list can be NULL which means hwc is temporarily disabled. 1970 // however, if dpy and sur are null it means we're turning the 1971 // screen off. no shall not call eglSwapBuffers() in that case. 1972 1973 if (hwc_dev->use_sgx) { 1974 if (!eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur)) { 1975 ALOGE("eglSwapBuffers error"); 1976 err = HWC_EGL_ERROR; 1977 goto err_out; 1978 } 1979 } 1980 1981 //dump_dsscomp(dsscomp); 1982 1983 // signal the event thread that a post has happened 1984 wakeup_hdmi_thread(hwc_dev); 1985 if (hwc_dev->force_sgx > 0) 1986 hwc_dev->force_sgx--; 1987 1988 hwc_dev->comp_data.blit_data.rgz_flags = hwc_dev->blit_flags; 1989 hwc_dev->comp_data.blit_data.rgz_items = hwc_dev->blit_num; 1990 int omaplfb_comp_data_sz = sizeof(hwc_dev->comp_data) + 1991 (hwc_dev->comp_data.blit_data.rgz_items * sizeof(struct rgz_blt_entry)); 1992 1993 1994 unsigned int nbufs = hwc_dev->post2_layers; 1995 if (hwc_dev->post2_blit_buffers) { 1996 /* 1997 * We don't want to pass a NULL entry in the Post2, but we need to 1998 * fix up buffer handle array and overlay indexes to account for 1999 * this 2000 */ 2001 nbufs += hwc_dev->post2_blit_buffers - 1; 2002 2003 if (hwc_dev->post2_layers > 1) { 2004 unsigned int i, j; 2005 for (i = 0; i < nbufs; i++) { 2006 hwc_dev->buffers[i] = hwc_dev->buffers[i+1]; 2007 } 2008 for (i = 1, j= 1; j < hwc_dev->post2_layers; i++, j++) { 2009 dsscomp->ovls[j].ba = i; 2010 } 2011 } 2012 } 2013 ALOGI_IF(debugblt && hwc_dev->blt_policy != BLTPOLICY_DISABLED, 2014 "Post2, blits %d, ovl_buffers %d, blit_buffers %d sgx %d", 2015 hwc_dev->blit_num, hwc_dev->post2_layers, hwc_dev->post2_blit_buffers, 2016 hwc_dev->use_sgx); 2017 2018 debug_post2(hwc_dev, nbufs); 2019 err = hwc_dev->fb_dev->Post2((framebuffer_device_t *)hwc_dev->fb_dev, 2020 hwc_dev->buffers, 2021 nbufs, 2022 dsscomp, omaplfb_comp_data_sz); 2023 showfps(); 2024 2025#if 0 2026 if (!hwc_dev->use_sgx) { 2027 __u32 crt = 0; 2028 int err2 = ioctl(hwc_dev->fb_fd, FBIO_WAITFORVSYNC, &crt); 2029 if (err2) { 2030 ALOGE("failed to wait for vsync (%d)", errno); 2031 err = err ? : -errno; 2032 } 2033 } 2034#endif 2035 } 2036 hwc_dev->last_ext_ovls = hwc_dev->ext_ovls; 2037 hwc_dev->last_int_ovls = hwc_dev->post2_layers; 2038 if (err) 2039 ALOGE("Post2 error"); 2040 2041 check_sync_fds(numDisplays, displays); 2042 2043err_out: 2044 pthread_mutex_unlock(&hwc_dev->lock); 2045 2046 if (invalidate && hwc_dev->procs && hwc_dev->procs->invalidate) 2047 hwc_dev->procs->invalidate(hwc_dev->procs); 2048 2049 return err; 2050} 2051 2052static void omap4_hwc_dump(struct hwc_composer_device_1 *dev, char *buff, int buff_len) 2053{ 2054 omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev; 2055 struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->comp_data.dsscomp_data; 2056 struct dump_buf log = { 2057 .buf = buff, 2058 .buf_len = buff_len, 2059 }; 2060 int i; 2061 2062 dump_printf(&log, "omap4_hwc %d:\n", dsscomp->num_ovls); 2063 dump_printf(&log, " idle timeout: %dms\n", hwc_dev->idle); 2064 2065 for (i = 0; i < dsscomp->num_ovls; i++) { 2066 struct dss2_ovl_cfg *cfg = &dsscomp->ovls[i].cfg; 2067 2068 dump_printf(&log, " layer %d:\n", i); 2069 dump_printf(&log, " enabled:%s buff:%p %dx%d stride:%d\n", 2070 cfg->enabled ? "true" : "false", hwc_dev->buffers[i], 2071 cfg->width, cfg->height, cfg->stride); 2072 dump_printf(&log, " src:(%d,%d) %dx%d dst:(%d,%d) %dx%d ix:%d zorder:%d\n", 2073 cfg->crop.x, cfg->crop.y, cfg->crop.w, cfg->crop.h, 2074 cfg->win.x, cfg->win.y, cfg->win.w, cfg->win.h, 2075 cfg->ix, cfg->zorder); 2076 } 2077 2078 if (hwc_dev->blt_policy != BLTPOLICY_DISABLED) { 2079 dump_printf(&log, " bltpolicy: %s, bltmode: %s\n", 2080 hwc_dev->blt_policy == BLTPOLICY_DEFAULT ? "default" : 2081 hwc_dev->blt_policy == BLTPOLICY_ALL ? "all" : "unknown", 2082 hwc_dev->blt_mode == BLTMODE_PAINT ? "paint" : "regionize"); 2083 } 2084 dump_printf(&log, "\n"); 2085} 2086 2087static void free_png_image(omap4_hwc_device_t *hwc_dev, struct omap4_hwc_img *img) 2088{ 2089 memset(img, 0, sizeof(*img)); 2090} 2091 2092static int load_png_image(omap4_hwc_device_t *hwc_dev, char *path, struct omap4_hwc_img *img) 2093{ 2094 void *ptr = NULL; 2095 png_bytepp row_pointers = NULL; 2096 2097 FILE *fd = fopen(path, "rb"); 2098 if (!fd) { 2099 ALOGE("failed to open PNG file %s: (%d)", path, errno); 2100 return -EINVAL; 2101 } 2102 2103 const int SIZE_PNG_HEADER = 8; 2104 __u8 header[SIZE_PNG_HEADER]; 2105 fread(header, 1, SIZE_PNG_HEADER, fd); 2106 if (png_sig_cmp(header, 0, SIZE_PNG_HEADER)) { 2107 ALOGE("%s is not a PNG file", path); 2108 goto fail; 2109 } 2110 2111 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 2112 if (!png_ptr) 2113 goto fail_alloc; 2114 png_infop info_ptr = png_create_info_struct(png_ptr); 2115 if (!info_ptr) 2116 goto fail_alloc; 2117 2118 if (setjmp(png_jmpbuf(png_ptr))) 2119 goto fail_alloc; 2120 2121 png_init_io(png_ptr, fd); 2122 png_set_sig_bytes(png_ptr, SIZE_PNG_HEADER); 2123 png_set_user_limits(png_ptr, limits.max_width, limits.max_height); 2124 png_read_info(png_ptr, info_ptr); 2125 2126 __u8 bit_depth = png_get_bit_depth(png_ptr, info_ptr); 2127 __u32 width = png_get_image_width(png_ptr, info_ptr); 2128 __u32 height = png_get_image_height(png_ptr, info_ptr); 2129 __u8 color_type = png_get_color_type(png_ptr, info_ptr); 2130 2131 switch (color_type) { 2132 case PNG_COLOR_TYPE_PALETTE: 2133 png_set_palette_to_rgb(png_ptr); 2134 png_set_filler(png_ptr, 128, PNG_FILLER_AFTER); 2135 break; 2136 case PNG_COLOR_TYPE_GRAY: 2137 if (bit_depth < 8) { 2138 png_set_expand_gray_1_2_4_to_8(png_ptr); 2139 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) 2140 png_set_tRNS_to_alpha(png_ptr); 2141 } else { 2142 png_set_filler(png_ptr, 128, PNG_FILLER_AFTER); 2143 } 2144 /* fall through */ 2145 case PNG_COLOR_TYPE_GRAY_ALPHA: 2146 png_set_gray_to_rgb(png_ptr); 2147 break; 2148 case PNG_COLOR_TYPE_RGB: 2149 png_set_filler(png_ptr, 128, PNG_FILLER_AFTER); 2150 /* fall through */ 2151 case PNG_COLOR_TYPE_RGB_ALPHA: 2152 png_set_bgr(png_ptr); 2153 break; 2154 default: 2155 ALOGE("unsupported PNG color: %x", color_type); 2156 goto fail_alloc; 2157 } 2158 2159 if (bit_depth == 16) 2160 png_set_strip_16(png_ptr); 2161 2162 const int bpp = 4; 2163 img->size = ALIGN(width * height * bpp, 4096); 2164 if (img->size > hwc_dev->img_mem_size) { 2165 ALOGE("image does not fit into framebuffer area (%d > %d)", img->size, hwc_dev->img_mem_size); 2166 goto fail_alloc; 2167 } 2168 img->ptr = hwc_dev->img_mem_ptr; 2169 2170 row_pointers = calloc(height, sizeof(*row_pointers)); 2171 if (!row_pointers) { 2172 ALOGE("failed to allocate row pointers"); 2173 goto fail_alloc; 2174 } 2175 __u32 i; 2176 for (i = 0; i < height; i++) 2177 row_pointers[i] = img->ptr + i * width * bpp; 2178 png_set_rows(png_ptr, info_ptr, row_pointers); 2179 png_read_update_info(png_ptr, info_ptr); 2180 img->rowbytes = png_get_rowbytes(png_ptr, info_ptr); 2181 2182 png_read_image(png_ptr, row_pointers); 2183 png_read_end(png_ptr, NULL); 2184 free(row_pointers); 2185 png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 2186 fclose(fd); 2187 img->width = width; 2188 img->height = height; 2189 return 0; 2190 2191fail_alloc: 2192 free_png_image(hwc_dev, img); 2193 free(row_pointers); 2194 if (!png_ptr || !info_ptr) 2195 ALOGE("failed to allocate PNG structures"); 2196 png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 2197fail: 2198 fclose(fd); 2199 return -EINVAL; 2200} 2201 2202 2203static int omap4_hwc_device_close(hw_device_t* device) 2204{ 2205 omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) device;; 2206 2207 if (hwc_dev) { 2208 if (hwc_dev->dsscomp_fd >= 0) 2209 close(hwc_dev->dsscomp_fd); 2210 if (hwc_dev->hdmi_fb_fd >= 0) 2211 close(hwc_dev->hdmi_fb_fd); 2212 if (hwc_dev->fb_fd >= 0) 2213 close(hwc_dev->fb_fd); 2214 if (hwc_dev->ion_fd >= 0) 2215 ion_close(hwc_dev->ion_fd); 2216 2217 /* pthread will get killed when parent process exits */ 2218 pthread_mutex_destroy(&hwc_dev->lock); 2219 pthread_mutex_destroy(&hwc_dev->vsync_lock); 2220 free(hwc_dev); 2221 } 2222 2223 return 0; 2224} 2225 2226static int omap4_hwc_open_fb_hal(IMG_framebuffer_device_public_t **fb_dev) 2227{ 2228 const struct hw_module_t *psModule; 2229 IMG_gralloc_module_public_t *psGrallocModule; 2230 int err; 2231 2232 err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &psModule); 2233 psGrallocModule = (IMG_gralloc_module_public_t *) psModule; 2234 2235 if(err) 2236 goto err_out; 2237 2238 if (strcmp(psGrallocModule->base.common.author, "Imagination Technologies")) { 2239 err = -EINVAL; 2240 goto err_out; 2241 } 2242 2243 *fb_dev = psGrallocModule->psFrameBufferDevice; 2244 2245 return 0; 2246 2247err_out: 2248 ALOGE("Composer HAL failed to load compatible Graphics HAL"); 2249 return err; 2250} 2251 2252static void set_primary_display_transform_matrix(omap4_hwc_device_t *hwc_dev) 2253{ 2254 /* create primary display translation matrix */ 2255 hwc_dev->fb_dis.ix = 0;/*Default display*/ 2256 2257 int ret = ioctl(hwc_dev->dsscomp_fd, DSSCIOC_QUERY_DISPLAY, &hwc_dev->fb_dis); 2258 if (ret) 2259 ALOGE("failed to get display info (%d): %m", errno); 2260 2261 int lcd_w = hwc_dev->fb_dis.timings.x_res; 2262 int lcd_h = hwc_dev->fb_dis.timings.y_res; 2263 int orig_w = hwc_dev->fb_dev->base.width; 2264 int orig_h = hwc_dev->fb_dev->base.height; 2265 hwc_rect_t region = {.left = 0, .top = 0, .right = orig_w, .bottom = orig_h}; 2266 hwc_dev->primary_region = region; 2267 hwc_dev->primary_rotation = ((lcd_w > lcd_h) ^ (orig_w > orig_h)) ? 1 : 0; 2268 hwc_dev->primary_transform = ((lcd_w != orig_w)||(lcd_h != orig_h)) ? 1 : 0; 2269 2270 ALOGI("transforming FB (%dx%d) => (%dx%d) rot%d", orig_w, orig_h, lcd_w, lcd_h, hwc_dev->primary_rotation); 2271 2272 /* reorientation matrix is: 2273 m = (center-from-target-center) * (scale-to-target) * (mirror) * (rotate) * (center-to-original-center) */ 2274 2275 memcpy(hwc_dev->primary_m, m_unit, sizeof(m_unit)); 2276 m_translate(hwc_dev->primary_m, -(orig_w >> 1), -(orig_h >> 1)); 2277 m_rotate(hwc_dev->primary_m, hwc_dev->primary_rotation); 2278 if (hwc_dev->primary_rotation & 1) 2279 swap(orig_w, orig_h); 2280 m_scale(hwc_dev->primary_m, orig_w, lcd_w, orig_h, lcd_h); 2281 m_translate(hwc_dev->primary_m, lcd_w >> 1, lcd_h >> 1); 2282} 2283 2284 2285static void handle_hotplug(omap4_hwc_device_t *hwc_dev) 2286{ 2287 omap4_hwc_ext_t *ext = &hwc_dev->ext; 2288 __u8 state = ext->hdmi_state; 2289 2290 /* Ignore external HDMI logic if the primary display is HDMI */ 2291 if (hwc_dev->on_tv) { 2292 ALOGI("Primary display is HDMI - skip clone/dock logic"); 2293 2294 if (state) { 2295 __u32 xres = hwc_dev->fb_dev->base.width; 2296 __u32 yres = hwc_dev->fb_dev->base.height; 2297 if (omap4_hwc_set_best_hdmi_mode(hwc_dev, xres, yres, ext->lcd_xpy)) { 2298 ALOGE("Failed to set HDMI mode"); 2299 } 2300 set_primary_display_transform_matrix(hwc_dev); 2301 2302 ioctl(hwc_dev->fb_fd, FBIOBLANK, FB_BLANK_UNBLANK); 2303 2304 if (hwc_dev->procs && hwc_dev->procs->invalidate) { 2305 hwc_dev->procs->invalidate(hwc_dev->procs); 2306 } 2307 } else 2308 ext->last_mode = 0; 2309 2310 return; 2311 } 2312 2313 pthread_mutex_lock(&hwc_dev->lock); 2314 ext->dock.enabled = ext->mirror.enabled = 0; 2315 if (state) { 2316 /* check whether we can clone and/or dock */ 2317 char value[PROPERTY_VALUE_MAX]; 2318 property_get("persist.hwc.docking.enabled", value, "1"); 2319 ext->dock.enabled = atoi(value) > 0; 2320 property_get("persist.hwc.mirroring.enabled", value, "1"); 2321 ext->mirror.enabled = atoi(value) > 0; 2322 property_get("persist.hwc.avoid_mode_change", value, "1"); 2323 ext->avoid_mode_change = atoi(value) > 0; 2324 2325 /* get cloning transformation */ 2326 property_get("persist.hwc.docking.transform", value, "0"); 2327 ext->dock.rotation = atoi(value) & EXT_ROTATION; 2328 ext->dock.hflip = (atoi(value) & EXT_HFLIP) > 0; 2329 ext->dock.docking = 1; 2330 property_get("persist.hwc.mirroring.transform", value, hwc_dev->fb_dis.timings.y_res > hwc_dev->fb_dis.timings.x_res ? "3" : "0"); 2331 ext->mirror.rotation = atoi(value) & EXT_ROTATION; 2332 ext->mirror.hflip = (atoi(value) & EXT_HFLIP) > 0; 2333 ext->mirror.docking = 0; 2334 2335 if (ext->force_dock) { 2336 /* restrict to docking with no transform */ 2337 ext->mirror.enabled = 0; 2338 ext->dock.rotation = 0; 2339 ext->dock.hflip = 0; 2340 2341 if (!dock_image.rowbytes) { 2342 property_get("persist.hwc.dock_image", value, "/vendor/res/images/dock/dock.png"); 2343 load_png_image(hwc_dev, value, &dock_image); 2344 } 2345 } 2346 2347 /* select best mode for mirroring */ 2348 if (ext->mirror.enabled) { 2349 ext->current = ext->mirror; 2350 ext->mirror_mode = 0; 2351 if (setup_mirroring(hwc_dev) == 0) { 2352 ext->mirror_mode = ext->last_mode; 2353 ioctl(hwc_dev->hdmi_fb_fd, FBIOBLANK, FB_BLANK_UNBLANK); 2354 } else 2355 ext->mirror.enabled = 0; 2356 } 2357 /* Allocate backup buffers for FB rotation 2358 * This is required only if the FB tranform is different from that 2359 * of the external display and the FB is not in TILER2D space 2360 */ 2361 if (ext->mirror.rotation && (limits.fbmem_type != DSSCOMP_FBMEM_TILER2D)) 2362 allocate_tiler2d_buffers(hwc_dev); 2363 2364 } else { 2365 ext->last_mode = 0; 2366 if (ext->mirror.rotation && (limits.fbmem_type != DSSCOMP_FBMEM_TILER2D)) { 2367 /* free tiler 2D buffer on detach */ 2368 free_tiler2d_buffers(hwc_dev); 2369 } 2370 } 2371 ALOGI("external display changed (state=%d, mirror={%s tform=%ddeg%s}, dock={%s tform=%ddeg%s%s}, tv=%d", state, 2372 ext->mirror.enabled ? "enabled" : "disabled", 2373 ext->mirror.rotation * 90, 2374 ext->mirror.hflip ? "+hflip" : "", 2375 ext->dock.enabled ? "enabled" : "disabled", 2376 ext->dock.rotation * 90, 2377 ext->dock.hflip ? "+hflip" : "", 2378 ext->force_dock ? " forced" : "", 2379 ext->on_tv); 2380 2381 pthread_mutex_unlock(&hwc_dev->lock); 2382 2383 /* hwc_dev->procs is set right after the device is opened, but there is 2384 * still a race condition where a hotplug event might occur after the open 2385 * but before the procs are registered. */ 2386 if (hwc_dev->procs && hwc_dev->procs->invalidate) 2387 hwc_dev->procs->invalidate(hwc_dev->procs); 2388} 2389 2390static void handle_uevents(omap4_hwc_device_t *hwc_dev, const char *buff, int len) 2391{ 2392 int dock; 2393 int hdmi; 2394 int vsync; 2395 int state = 0; 2396 uint64_t timestamp = 0; 2397 const char *s = buff; 2398 2399 dock = !strcmp(s, "change@/devices/virtual/switch/dock"); 2400 hdmi = !strcmp(s, "change@/devices/virtual/switch/hdmi"); 2401 vsync = !strcmp(s, "change@/devices/platform/omapfb") || 2402 !strcmp(s, "change@/devices/virtual/switch/omapfb-vsync"); 2403 2404 if (!dock && !vsync && !hdmi) 2405 return; 2406 2407 s += strlen(s) + 1; 2408 2409 while(*s) { 2410 if (!strncmp(s, "SWITCH_STATE=", strlen("SWITCH_STATE="))) 2411 state = atoi(s + strlen("SWITCH_STATE=")); 2412 else if (!strncmp(s, "SWITCH_TIME=", strlen("SWITCH_TIME="))) 2413 timestamp = strtoull(s + strlen("SWITCH_TIME="), NULL, 0); 2414 else if (!strncmp(s, "VSYNC=", strlen("VSYNC="))) 2415 timestamp = strtoull(s + strlen("VSYNC="), NULL, 0); 2416 2417 s += strlen(s) + 1; 2418 if (s - buff >= len) 2419 break; 2420 } 2421 2422 if (vsync) { 2423 fire_vsync_event(hwc_dev, timestamp); 2424 } else { 2425 if (dock) { 2426 hwc_dev->ext.force_dock = state == 1; 2427 } else { 2428 /* If the primary display is HDMI, VSYNC is enabled, and HDMI's plug 2429 * state has just gone from 1->0, then we need to be sure to start 2430 * faking the VSYNC events. 2431 */ 2432 if (hwc_dev->on_tv) { 2433 int new_state, state_change; 2434 2435 pthread_mutex_lock(&hwc_dev->vsync_lock); 2436 2437 new_state = state == 1; 2438 state_change = (new_state != hwc_dev->ext.hdmi_state); 2439 hwc_dev->ext.hdmi_state = new_state; 2440 if (state_change && !new_state) 2441 wakeup_hdmi_thread(hwc_dev); 2442 2443 pthread_mutex_unlock(&hwc_dev->vsync_lock); 2444 } else { 2445 hwc_dev->ext.hdmi_state = state == 1; 2446 } 2447 } 2448 handle_hotplug(hwc_dev); 2449 } 2450} 2451 2452static void *omap4_hwc_hdmi_thread(void *data) 2453{ 2454 omap4_hwc_device_t *hwc_dev = data; 2455 static char uevent_desc[4096]; 2456 struct pollfd fds[2]; 2457 int invalidate = 0; 2458 int timeout; 2459 int err; 2460 2461 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY); 2462 2463 uevent_init(); 2464 2465 fds[0].fd = uevent_get_fd(); 2466 fds[0].events = POLLIN; 2467 fds[1].fd = hwc_dev->wakeup_evt; 2468 fds[1].events = POLLIN; 2469 2470 timeout = hwc_dev->idle ? hwc_dev->idle : -1; 2471 2472 memset(uevent_desc, 0, sizeof(uevent_desc)); 2473 2474 do { 2475 uint64_t idle_wakeup = (uint64_t)(-1); 2476 uint64_t vsync_wakeup = (uint64_t)(-1); 2477 uint64_t now = vsync_clock_now(); 2478 uint64_t effective_wakeup; 2479 int effective_timeout; 2480 2481 if (timeout >= 0) 2482 idle_wakeup = now + (((uint64_t)timeout) * 1000000); 2483 2484 if (hwc_dev->on_tv) { 2485 pthread_mutex_lock(&hwc_dev->vsync_lock); 2486 2487 if (!hwc_dev->ext.hdmi_state && hwc_dev->vsync_enabled) { 2488 vsync_wakeup = hwc_dev->last_vsync_time_valid 2489 ? hwc_dev->last_vsync_time 2490 : now; 2491 2492 vsync_wakeup += hwc_dev->fake_vsync_period; 2493 2494 if (vsync_wakeup < now) 2495 vsync_wakeup = now; 2496 } 2497 2498 pthread_mutex_unlock(&hwc_dev->vsync_lock); 2499 } 2500 2501 effective_wakeup = idle_wakeup < vsync_wakeup 2502 ? idle_wakeup 2503 : vsync_wakeup; 2504 if (effective_wakeup == (uint64_t)(-1)) 2505 effective_timeout = -1; 2506 else if (effective_wakeup <= now) 2507 effective_timeout = 0; 2508 else 2509 effective_timeout = (int)((effective_wakeup - now + 999999) / 1000000); 2510 2511 if (effective_timeout) 2512 err = poll(fds, 2, effective_timeout); 2513 else 2514 err = 0; 2515 2516 now = vsync_clock_now(); 2517 2518 if (err == 0) { 2519 int fired = 0; 2520 2521 if (now >= vsync_wakeup) { 2522 fire_vsync_event(hwc_dev, vsync_wakeup); 2523 fired = 1; 2524 } 2525 2526 if (hwc_dev->idle && (now >= idle_wakeup)) { 2527 if (hwc_dev->procs) { 2528 pthread_mutex_lock(&hwc_dev->lock); 2529 invalidate = !hwc_dev->force_sgx; 2530 if (invalidate) { 2531 hwc_dev->force_sgx = 2; 2532 } 2533 pthread_mutex_unlock(&hwc_dev->lock); 2534 2535 if (invalidate) { 2536 hwc_dev->procs->invalidate(hwc_dev->procs); 2537 timeout = -1; 2538 } 2539 } 2540 2541 fired = 1; 2542 } 2543 2544 if (fired) 2545 continue; 2546 } 2547 2548 if (err == -1) { 2549 if (errno != EINTR) 2550 ALOGE("event error: %m"); 2551 continue; 2552 } 2553 2554 if (fds[1].revents & POLLIN) { 2555 uint64_t tmp; 2556 2557 read(hwc_dev->wakeup_evt, &tmp, sizeof(tmp)); 2558 2559 if (!hwc_dev->force_sgx) 2560 timeout = hwc_dev->idle ? hwc_dev->idle : -1; 2561 } 2562 2563 if (fds[0].revents & POLLIN) { 2564 /* keep last 2 zeroes to ensure double 0 termination */ 2565 int len = uevent_next_event(uevent_desc, sizeof(uevent_desc) - 2); 2566 handle_uevents(hwc_dev, uevent_desc, len); 2567 } 2568 } while (1); 2569 2570 return NULL; 2571} 2572 2573static void omap4_hwc_registerProcs(struct hwc_composer_device_1* dev, 2574 hwc_procs_t const* procs) 2575{ 2576 omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) dev; 2577 2578 hwc_dev->procs = (typeof(hwc_dev->procs)) procs; 2579} 2580 2581static int omap4_hwc_query(struct hwc_composer_device_1* dev, 2582 int what, int* value) 2583{ 2584 omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) dev; 2585 2586 switch (what) { 2587 case HWC_BACKGROUND_LAYER_SUPPORTED: 2588 // we don't support the background layer yet 2589 value[0] = 0; 2590 break; 2591 case HWC_VSYNC_PERIOD: 2592 // vsync period in nanosecond 2593 value[0] = 1000000000.0 / hwc_dev->fb_dev->base.fps; 2594 break; 2595 default: 2596 // unsupported query 2597 return -EINVAL; 2598 } 2599 return 0; 2600} 2601 2602static int omap4_hwc_event_control(struct hwc_composer_device_1* dev, 2603 int dpy, int event, int enabled) 2604{ 2605 omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) dev; 2606 2607 switch (event) { 2608 case HWC_EVENT_VSYNC: 2609 { 2610 int val = !!enabled; 2611 int err; 2612 2613 /* If the primary display is HDMI, then we need to be sure to fake a 2614 * stream vsync events if vsync is enabled, but HDMI happens to be 2615 * disconnected. 2616 */ 2617 if (hwc_dev->on_tv) { 2618 pthread_mutex_lock(&hwc_dev->vsync_lock); 2619 2620 if (!val) 2621 hwc_dev->last_vsync_time_valid = 0; 2622 2623 /* If VSYNC is enabled, but HDMI is not actually plugged in, we need 2624 * to fake it. Poke the work thread to make sure it is taking care 2625 * of things. 2626 */ 2627 if (!hwc_dev->ext.hdmi_state && !hwc_dev->vsync_enabled && val) 2628 wakeup_hdmi_thread(hwc_dev); 2629 2630 hwc_dev->vsync_enabled = val; 2631 2632 err = ioctl(hwc_dev->fb_fd, OMAPFB_ENABLEVSYNC, &val); 2633 pthread_mutex_unlock(&hwc_dev->vsync_lock); 2634 } else { 2635 err = ioctl(hwc_dev->fb_fd, OMAPFB_ENABLEVSYNC, &val); 2636 } 2637 2638 if (err < 0) 2639 return -errno; 2640 2641 return 0; 2642 } 2643 default: 2644 return -EINVAL; 2645 } 2646} 2647 2648static int omap4_hwc_blank(struct hwc_composer_device_1 *dev, int dpy, int blank) 2649{ 2650 // We're using an older method of screen blanking based on 2651 // early_suspend in the kernel. No need to do anything here. 2652 return 0; 2653} 2654 2655static int omap4_hwc_device_open(const hw_module_t* module, const char* name, 2656 hw_device_t** device) 2657{ 2658 omap4_hwc_module_t *hwc_mod = (omap4_hwc_module_t *)module; 2659 omap4_hwc_device_t *hwc_dev; 2660 int err = 0; 2661 2662 if (strcmp(name, HWC_HARDWARE_COMPOSER)) { 2663 return -EINVAL; 2664 } 2665 2666 if (!hwc_mod->fb_dev) { 2667 err = omap4_hwc_open_fb_hal(&hwc_mod->fb_dev); 2668 if (err) 2669 return err; 2670 2671 if (!hwc_mod->fb_dev) { 2672 ALOGE("Framebuffer HAL not opened before HWC"); 2673 return -EFAULT; 2674 } 2675 hwc_mod->fb_dev->bBypassPost = 1; 2676 } 2677 2678 hwc_dev = (omap4_hwc_device_t *)malloc(sizeof(*hwc_dev)); 2679 if (hwc_dev == NULL) 2680 return -ENOMEM; 2681 2682 memset(hwc_dev, 0, sizeof(*hwc_dev)); 2683 2684 hwc_dev->base.common.tag = HARDWARE_DEVICE_TAG; 2685 hwc_dev->base.common.version = HWC_DEVICE_API_VERSION_1_0; 2686 hwc_dev->base.common.module = (hw_module_t *)module; 2687 hwc_dev->base.common.close = omap4_hwc_device_close; 2688 hwc_dev->base.prepare = omap4_hwc_prepare; 2689 hwc_dev->base.set = omap4_hwc_set; 2690 hwc_dev->base.eventControl = omap4_hwc_event_control; 2691 hwc_dev->base.blank = omap4_hwc_blank; 2692 hwc_dev->base.query = omap4_hwc_query; 2693 hwc_dev->base.registerProcs = omap4_hwc_registerProcs; 2694 hwc_dev->base.dump = omap4_hwc_dump; 2695 hwc_dev->fb_dev = hwc_mod->fb_dev; 2696 hwc_dev->wakeup_evt = -1; 2697 *device = &hwc_dev->base.common; 2698 2699 hwc_dev->vsync_enabled = 0; 2700 hwc_dev->last_vsync_time_valid = 0; 2701 hwc_dev->fake_vsync_period = 1000000000ull/60; 2702 2703 hwc_dev->dsscomp_fd = open("/dev/dsscomp", O_RDWR); 2704 if (hwc_dev->dsscomp_fd < 0) { 2705 ALOGE("failed to open dsscomp (%d)", errno); 2706 err = -errno; 2707 goto done; 2708 } 2709 2710 int ret = ioctl(hwc_dev->dsscomp_fd, DSSCIOC_QUERY_PLATFORM, &limits); 2711 if (ret) { 2712 ALOGE("failed to get platform limits (%d): %m", errno); 2713 err = -errno; 2714 goto done; 2715 } 2716 2717 hwc_dev->fb_fd = open("/dev/graphics/fb0", O_RDWR); 2718 if (hwc_dev->fb_fd < 0) { 2719 ALOGE("failed to open fb (%d)", errno); 2720 err = -errno; 2721 goto done; 2722 } 2723 2724 struct fb_fix_screeninfo fix; 2725 if (ioctl(hwc_dev->fb_fd, FBIOGET_FSCREENINFO, &fix)) { 2726 ALOGE("failed to get fb info (%d)", errno); 2727 err = -errno; 2728 goto done; 2729 } 2730 2731 hwc_dev->img_mem_size = fix.smem_len; 2732 hwc_dev->img_mem_ptr = mmap(NULL, fix.smem_len, PROT_WRITE, MAP_SHARED, hwc_dev->fb_fd, 0); 2733 if (hwc_dev->img_mem_ptr == MAP_FAILED) { 2734 ALOGE("failed to map fb memory"); 2735 err = -errno; 2736 goto done; 2737 } 2738 2739 /* Allocate the maximum buffers that we can receive from HWC */ 2740 hwc_dev->buffers = malloc(sizeof(buffer_handle_t) * MAX_HWC_LAYERS); 2741 if (!hwc_dev->buffers) { 2742 err = -ENOMEM; 2743 goto done; 2744 } 2745 2746 ret = ioctl(hwc_dev->dsscomp_fd, DSSCIOC_QUERY_DISPLAY, &hwc_dev->fb_dis); 2747 if (ret) { 2748 ALOGE("failed to get display info (%d): %m", errno); 2749 err = -errno; 2750 goto done; 2751 } 2752 2753 hwc_dev->ion_fd = ion_open(); 2754 if (hwc_dev->ion_fd < 0) { 2755 ALOGE("failed to open ion driver (%d)", errno); 2756 } 2757 2758 int i; 2759 for (i = 0; i < NUM_EXT_DISPLAY_BACK_BUFFERS; i++) { 2760 hwc_dev->ion_handles[i] = NULL; 2761 } 2762 2763 /* use default value in case some of requested display parameters missing */ 2764 hwc_dev->ext.lcd_xpy = 1.0; 2765 if (hwc_dev->fb_dis.timings.x_res && hwc_dev->fb_dis.height_in_mm) { 2766 hwc_dev->ext.lcd_xpy = (float) 2767 hwc_dev->fb_dis.width_in_mm / hwc_dev->fb_dis.timings.x_res / 2768 hwc_dev->fb_dis.height_in_mm * hwc_dev->fb_dis.timings.y_res; 2769 } 2770 2771 if (hwc_dev->fb_dis.channel == OMAP_DSS_CHANNEL_DIGIT) { 2772 ALOGI("Primary display is HDMI"); 2773 hwc_dev->on_tv = 1; 2774 } 2775 else { 2776 hwc_dev->hdmi_fb_fd = open("/dev/graphics/fb1", O_RDWR); 2777 if (hwc_dev->hdmi_fb_fd < 0) { 2778 ALOGE("failed to open hdmi fb (%d)", errno); 2779 err = -errno; 2780 goto done; 2781 } 2782 } 2783 set_primary_display_transform_matrix(hwc_dev); 2784 2785 if ((hwc_dev->wakeup_evt = eventfd(0, EFD_NONBLOCK)) < 0) { 2786 ALOGE("failed to eventfd (%d): %m", errno); 2787 err = -errno; 2788 goto done; 2789 } 2790 2791 if (pthread_mutex_init(&hwc_dev->lock, NULL)) { 2792 ALOGE("failed to create mutex (%d): %m", errno); 2793 err = -errno; 2794 goto done; 2795 } 2796 2797 if (pthread_mutex_init(&hwc_dev->vsync_lock, NULL)) { 2798 ALOGE("failed to create vsync mutex (%d): %m", errno); 2799 err = -errno; 2800 goto done; 2801 } 2802 2803 if (pthread_create(&hwc_dev->hdmi_thread, NULL, omap4_hwc_hdmi_thread, hwc_dev)) 2804 { 2805 ALOGE("failed to create HDMI listening thread (%d): %m", errno); 2806 err = -errno; 2807 goto done; 2808 } 2809 2810 /* get debug properties */ 2811 2812 /* see if hwc is enabled at all */ 2813 char value[PROPERTY_VALUE_MAX]; 2814 property_get("debug.hwc.rgb_order", value, "1"); 2815 hwc_dev->flags_rgb_order = atoi(value); 2816 property_get("debug.hwc.nv12_only", value, "0"); 2817 hwc_dev->flags_nv12_only = atoi(value); 2818 property_get("debug.hwc.idle", value, "250"); 2819 hwc_dev->idle = atoi(value); 2820 2821 /* get the board specific clone properties */ 2822 /* 0:0:1280:720 */ 2823 if (property_get("persist.hwc.mirroring.region", value, "") <= 0 || 2824 sscanf(value, "%d:%d:%d:%d", 2825 &hwc_dev->ext.mirror_region.left, &hwc_dev->ext.mirror_region.top, 2826 &hwc_dev->ext.mirror_region.right, &hwc_dev->ext.mirror_region.bottom) != 4 || 2827 hwc_dev->ext.mirror_region.left >= hwc_dev->ext.mirror_region.right || 2828 hwc_dev->ext.mirror_region.top >= hwc_dev->ext.mirror_region.bottom) { 2829 struct hwc_rect fb_region = { .right = hwc_dev->fb_dev->base.width, .bottom = hwc_dev->fb_dev->base.height }; 2830 hwc_dev->ext.mirror_region = fb_region; 2831 } 2832 ALOGI("clone region is set to (%d,%d) to (%d,%d)", 2833 hwc_dev->ext.mirror_region.left, hwc_dev->ext.mirror_region.top, 2834 hwc_dev->ext.mirror_region.right, hwc_dev->ext.mirror_region.bottom); 2835 2836 /* read switch state */ 2837 int sw_fd = open("/sys/class/switch/hdmi/state", O_RDONLY); 2838 if (sw_fd >= 0) { 2839 char value; 2840 if (read(sw_fd, &value, 1) == 1) 2841 hwc_dev->ext.hdmi_state = value == '1'; 2842 close(sw_fd); 2843 } 2844 sw_fd = open("/sys/class/switch/dock/state", O_RDONLY); 2845 if (sw_fd >= 0) { 2846 char value; 2847 if (read(sw_fd, &value, 1) == 1) 2848 hwc_dev->ext.force_dock = value == '1'; 2849 close(sw_fd); 2850 } 2851 handle_hotplug(hwc_dev); 2852 2853 ALOGI("omap4_hwc_device_open(rgb_order=%d nv12_only=%d)", 2854 hwc_dev->flags_rgb_order, hwc_dev->flags_nv12_only); 2855 2856 int gc2d_fd = open("/dev/gcioctl", O_RDWR); 2857 if (gc2d_fd < 0) { 2858 ALOGI("Unable to open gc-core device (%d), blits disabled", errno); 2859 hwc_dev->blt_policy = BLTPOLICY_DISABLED; 2860 } else { 2861 property_get("persist.hwc.bltmode", value, "1"); 2862 hwc_dev->blt_mode = atoi(value); 2863 property_get("persist.hwc.bltpolicy", value, "1"); 2864 hwc_dev->blt_policy = atoi(value); 2865 ALOGI("blitter present, blits mode %d, blits policy %d", hwc_dev->blt_mode, hwc_dev->blt_policy); 2866 close(gc2d_fd); 2867 2868 if (rgz_get_screengeometry(hwc_dev->fb_fd, &gscrngeom, 2869 hwc_dev->fb_dev->base.format) != 0) { 2870 err = -EINVAL; 2871 goto done; 2872 } 2873 } 2874 2875 property_get("persist.hwc.upscaled_nv12_limit", value, "2."); 2876 sscanf(value, "%f", &hwc_dev->upscaled_nv12_limit); 2877 if (hwc_dev->upscaled_nv12_limit < 0. || hwc_dev->upscaled_nv12_limit > 2048.) { 2878 ALOGW("Invalid upscaled_nv12_limit (%s), setting to 2.", value); 2879 hwc_dev->upscaled_nv12_limit = 2.; 2880 } 2881 2882done: 2883 if (err && hwc_dev) { 2884 if (hwc_dev->dsscomp_fd >= 0) 2885 close(hwc_dev->dsscomp_fd); 2886 if (hwc_dev->hdmi_fb_fd >= 0) 2887 close(hwc_dev->hdmi_fb_fd); 2888 if (hwc_dev->fb_fd >= 0) 2889 close(hwc_dev->fb_fd); 2890 if (hwc_dev->wakeup_evt >= 0) 2891 close(hwc_dev->wakeup_evt); 2892 pthread_mutex_destroy(&hwc_dev->lock); 2893 pthread_mutex_destroy(&hwc_dev->vsync_lock); 2894 free(hwc_dev->buffers); 2895 free(hwc_dev); 2896 } 2897 2898 return err; 2899} 2900 2901static struct hw_module_methods_t omap4_hwc_module_methods = { 2902 .open = omap4_hwc_device_open, 2903}; 2904 2905omap4_hwc_module_t HAL_MODULE_INFO_SYM = { 2906 .base = { 2907 .common = { 2908 .tag = HARDWARE_MODULE_TAG, 2909 .module_api_version = HWC_MODULE_API_VERSION_0_1, 2910 .hal_api_version = HARDWARE_HAL_API_VERSION, 2911 .id = HWC_HARDWARE_MODULE_ID, 2912 .name = "OMAP 44xx Hardware Composer HAL", 2913 .author = "Texas Instruments", 2914 .methods = &omap4_hwc_module_methods, 2915 }, 2916 }, 2917}; 2918