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