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