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/ioctl.h> 24 #include <linux/fb.h> 25 #include <linux/omapfb.h> 26 #include <sys/mman.h> 27 #include <sys/resource.h> 28 29 #include <cutils/properties.h> 30 #include <cutils/log.h> 31 #include <cutils/native_handle.h> 32 #include <hardware/hardware.h> 33 #include <hardware/hwcomposer.h> 34 #include <EGL/egl.h> 35 #include <hardware_legacy/uevent.h> 36 #include <png.h> 37 38 #include <system/graphics.h> 39 40 #define ASPECT_RATIO_TOLERANCE 0.02f 41 42 #define min(a, b) ( { typeof(a) __a = (a), __b = (b); __a < __b ? __a : __b; } ) 43 #define max(a, b) ( { typeof(a) __a = (a), __b = (b); __a > __b ? __a : __b; } ) 44 #define swap(a, b) do { typeof(a) __a = (a); (a) = (b); (b) = __a; } while (0) 45 46 #define WIDTH(rect) ((rect).right - (rect).left) 47 #define HEIGHT(rect) ((rect).bottom - (rect).top) 48 49 #define DIV_ROUND_UP(a, b) (((a) + (b) - 1) / (b)) 50 51 #include <video/dsscomp.h> 52 53 #include "hal_public.h" 54 55 #define MAX_HW_OVERLAYS 4 56 #define NUM_NONSCALING_OVERLAYS 1 57 #define HAL_PIXEL_FORMAT_BGRX_8888 0x1FF 58 #define HAL_PIXEL_FORMAT_TI_NV12 0x100 59 #define HAL_PIXEL_FORMAT_TI_NV12_PADDED 0x101 60 #define MAX_TILER_SLOT (16 << 20) 61 62 struct ext_transform_t { 63 __u8 rotation : 3; /* 90-degree clockwise rotations */ 64 __u8 hflip : 1; /* flip l-r (after rotation) */ 65 __u8 enabled : 1; /* cloning enabled */ 66 __u8 docking : 1; /* docking vs. mirroring - used for state */ 67 }; 68 69 /* cloning support and state */ 70 struct omap4_hwc_ext { 71 /* support */ 72 struct ext_transform_t mirror; /* mirroring settings */ 73 struct ext_transform_t dock; /* docking settings */ 74 float lcd_xpy; /* pixel ratio for UI */ 75 __u8 avoid_mode_change; /* use HDMI mode used for mirroring if possible */ 76 __u8 force_dock; /* must dock */ 77 __u8 hdmi_state; /* whether HDMI is connected */ 78 79 /* state */ 80 __u8 on_tv; /* using a tv */ 81 struct ext_transform_t current; /* current settings */ 82 struct ext_transform_t last; /* last-used settings */ 83 84 /* configuration */ 85 __u32 last_xres_used; /* resolution and pixel ratio used for mode selection */ 86 __u32 last_yres_used; 87 __u32 last_mode; /* 2-s complement of last HDMI mode set, 0 if none */ 88 __u32 mirror_mode; /* 2-s complement of mode used when mirroring */ 89 float last_xpy; 90 __u16 width; /* external screen dimensions */ 91 __u16 height; 92 __u32 xres; /* external screen resolution */ 93 __u32 yres; 94 float m[2][3]; /* external transformation matrix */ 95 hwc_rect_t mirror_region; /* region of screen to mirror */ 96 }; 97 typedef struct omap4_hwc_ext omap4_hwc_ext_t; 98 99 /* used by property settings */ 100 enum { 101 EXT_ROTATION = 3, /* rotation while mirroring */ 102 EXT_HFLIP = (1 << 2), /* flip l-r on output (after rotation) */ 103 }; 104 105 /* ARGB image */ 106 struct omap4_hwc_img { 107 int width; 108 int height; 109 int rowbytes; 110 int size; 111 unsigned char *ptr; 112 } dock_image = { .rowbytes = 0 }; 113 114 struct omap4_hwc_module { 115 hwc_module_t base; 116 117 IMG_framebuffer_device_public_t *fb_dev; 118 }; 119 typedef struct omap4_hwc_module omap4_hwc_module_t; 120 121 struct omap4_hwc_device { 122 /* static data */ 123 hwc_composer_device_t base; 124 hwc_procs_t *procs; 125 pthread_t hdmi_thread; 126 pthread_mutex_t lock; 127 128 IMG_framebuffer_device_public_t *fb_dev; 129 struct dsscomp_display_info fb_dis; 130 int fb_fd; /* file descriptor for /dev/fb0 */ 131 int dsscomp_fd; /* file descriptor for /dev/dsscomp */ 132 int hdmi_fb_fd; /* file descriptor for /dev/fb1 */ 133 int pipe_fds[2]; /* pipe to event thread */ 134 135 int img_mem_size; /* size of fb for hdmi */ 136 void *img_mem_ptr; /* start of fb for hdmi */ 137 138 int flags_rgb_order; 139 int flags_nv12_only; 140 141 int force_sgx; 142 omap4_hwc_ext_t ext; /* external mirroring data */ 143 int idle; 144 int ovls_blending; 145 146 /* composition data */ 147 struct dsscomp_setup_dispc_data dsscomp_data; 148 buffer_handle_t *buffers; 149 int use_sgx; 150 int swap_rb; 151 unsigned int post2_layers; 152 int ext_ovls; /* # of overlays on external display for current composition */ 153 int ext_ovls_wanted; /* # of overlays that should be on external display for current composition */ 154 int last_ext_ovls; /* # of overlays on external/internal display for last composition */ 155 int last_int_ovls; 156 }; 157 typedef struct omap4_hwc_device omap4_hwc_device_t; 158 159 #define HAL_FMT(f) ((f) == HAL_PIXEL_FORMAT_TI_NV12 ? "NV12" : \ 160 (f) == HAL_PIXEL_FORMAT_YV12 ? "YV12" : \ 161 (f) == HAL_PIXEL_FORMAT_BGRX_8888 ? "xRGB32" : \ 162 (f) == HAL_PIXEL_FORMAT_RGBX_8888 ? "xBGR32" : \ 163 (f) == HAL_PIXEL_FORMAT_BGRA_8888 ? "ARGB32" : \ 164 (f) == HAL_PIXEL_FORMAT_RGBA_8888 ? "ABGR32" : \ 165 (f) == HAL_PIXEL_FORMAT_RGB_565 ? "RGB565" : "??") 166 167 #define DSS_FMT(f) ((f) == OMAP_DSS_COLOR_NV12 ? "NV12" : \ 168 (f) == OMAP_DSS_COLOR_RGB24U ? "xRGB32" : \ 169 (f) == OMAP_DSS_COLOR_ARGB32 ? "ARGB32" : \ 170 (f) == OMAP_DSS_COLOR_RGB16 ? "RGB565" : "??") 171 172 static int debug = 0; 173 174 static void dump_layer(hwc_layer_t const* l) 175 { 176 ALOGD("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}", 177 l->compositionType, l->flags, l->handle, l->transform, l->blending, 178 l->sourceCrop.left, 179 l->sourceCrop.top, 180 l->sourceCrop.right, 181 l->sourceCrop.bottom, 182 l->displayFrame.left, 183 l->displayFrame.top, 184 l->displayFrame.right, 185 l->displayFrame.bottom); 186 } 187 188 static void dump_dsscomp(struct dsscomp_setup_dispc_data *d) 189 { 190 unsigned i; 191 192 ALOGD("[%08x] set: %c%c%c %d ovls\n", 193 d->sync_id, 194 (d->mode & DSSCOMP_SETUP_MODE_APPLY) ? 'A' : '-', 195 (d->mode & DSSCOMP_SETUP_MODE_DISPLAY) ? 'D' : '-', 196 (d->mode & DSSCOMP_SETUP_MODE_CAPTURE) ? 'C' : '-', 197 d->num_ovls); 198 199 for (i = 0; i < d->num_mgrs; i++) { 200 struct dss2_mgr_info *mi = &d->mgrs[i]; 201 ALOGD(" (dis%d alpha=%d col=%08x ilace=%d)\n", 202 mi->ix, 203 mi->alpha_blending, mi->default_color, 204 mi->interlaced); 205 } 206 207 for (i = 0; i < d->num_ovls; i++) { 208 struct dss2_ovl_info *oi = &d->ovls[i]; 209 struct dss2_ovl_cfg *c = &oi->cfg; 210 if (c->zonly) 211 ALOGD("ovl%d(%s z%d)\n", 212 c->ix, c->enabled ? "ON" : "off", c->zorder); 213 else 214 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", 215 c->ix, c->enabled ? "ON" : "off", c->zorder, DSS_FMT(c->color_mode), 216 c->pre_mult_alpha ? " premult" : "", 217 (c->global_alpha * 100 + 128) / 255, 218 c->width, c->height, c->crop.x, c->crop.y, 219 c->crop.w, c->crop.h, 220 c->rotation, c->mirror ? "+mir" : "", 221 c->win.x, c->win.y, c->win.w, c->win.h, 222 (void *) oi->ba, (void *) oi->uv, c->stride); 223 } 224 } 225 226 struct dump_buf { 227 char *buf; 228 int buf_len; 229 int len; 230 }; 231 232 static void dump_printf(struct dump_buf *buf, const char *fmt, ...) 233 { 234 va_list ap; 235 236 va_start(ap, fmt); 237 buf->len += vsnprintf(buf->buf + buf->len, buf->buf_len - buf->len, fmt, ap); 238 va_end(ap); 239 } 240 241 static void dump_set_info(omap4_hwc_device_t *hwc_dev, hwc_layer_list_t* list) 242 { 243 struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->dsscomp_data; 244 char logbuf[1024]; 245 struct dump_buf log = { 246 .buf = logbuf, 247 .buf_len = sizeof(logbuf), 248 }; 249 unsigned int i; 250 251 dump_printf(&log, "set H{"); 252 for (i = 0; list && i < list->numHwLayers; i++) { 253 if (i) 254 dump_printf(&log, " "); 255 hwc_layer_t *layer = &list->hwLayers[i]; 256 IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; 257 dump_printf(&log, "%p:%s,", handle, layer->compositionType == HWC_OVERLAY ? "DSS" : "SGX"); 258 if ((layer->flags & HWC_SKIP_LAYER) || !handle) { 259 dump_printf(&log, "SKIP"); 260 continue; 261 } 262 if (layer->flags & HWC_HINT_CLEAR_FB) 263 dump_printf(&log, "CLR,"); 264 dump_printf(&log, "%d*%d(%s)", handle->iWidth, handle->iHeight, HAL_FMT(handle->iFormat)); 265 if (layer->transform) 266 dump_printf(&log, "~%d", layer->transform); 267 } 268 dump_printf(&log, "} D{"); 269 for (i = 0; i < dsscomp->num_ovls; i++) { 270 if (i) 271 dump_printf(&log, " "); 272 dump_printf(&log, "%d=", dsscomp->ovls[i].cfg.ix); 273 if (dsscomp->ovls[i].cfg.enabled) 274 dump_printf(&log, "%08x:%d*%d,%s", 275 dsscomp->ovls[i].ba, 276 dsscomp->ovls[i].cfg.width, 277 dsscomp->ovls[i].cfg.height, 278 DSS_FMT(dsscomp->ovls[i].cfg.color_mode)); 279 else 280 dump_printf(&log, "-"); 281 } 282 dump_printf(&log, "} L{"); 283 for (i = 0; i < hwc_dev->post2_layers; i++) { 284 if (i) 285 dump_printf(&log, " "); 286 dump_printf(&log, "%p", hwc_dev->buffers[i]); 287 } 288 dump_printf(&log, "}%s\n", hwc_dev->use_sgx ? " swap" : ""); 289 290 ALOGD("%s", log.buf); 291 } 292 293 static int sync_id = 0; 294 295 static int omap4_hwc_is_valid_format(int format) 296 { 297 switch(format) { 298 case HAL_PIXEL_FORMAT_RGB_565: 299 case HAL_PIXEL_FORMAT_RGBX_8888: 300 case HAL_PIXEL_FORMAT_RGBA_8888: 301 case HAL_PIXEL_FORMAT_BGRA_8888: 302 case HAL_PIXEL_FORMAT_BGRX_8888: 303 case HAL_PIXEL_FORMAT_TI_NV12: 304 case HAL_PIXEL_FORMAT_TI_NV12_PADDED: 305 return 1; 306 307 default: 308 return 0; 309 } 310 } 311 312 static int scaled(hwc_layer_t *layer) 313 { 314 int w = WIDTH(layer->sourceCrop); 315 int h = HEIGHT(layer->sourceCrop); 316 317 if (layer->transform & HWC_TRANSFORM_ROT_90) 318 swap(w, h); 319 320 return WIDTH(layer->displayFrame) != w || HEIGHT(layer->displayFrame) != h; 321 } 322 323 static int is_protected(hwc_layer_t *layer) 324 { 325 IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; 326 327 return (handle->usage & GRALLOC_USAGE_PROTECTED); 328 } 329 330 #define is_BLENDED(layer) ((layer)->blending != HWC_BLENDING_NONE) 331 332 static int is_RGB(IMG_native_handle_t *handle) 333 { 334 switch(handle->iFormat) 335 { 336 case HAL_PIXEL_FORMAT_BGRA_8888: 337 case HAL_PIXEL_FORMAT_BGRX_8888: 338 case HAL_PIXEL_FORMAT_RGB_565: 339 return 1; 340 default: 341 return 0; 342 } 343 } 344 345 static int is_BGR_format(int format) 346 { 347 switch (format) { 348 case HAL_PIXEL_FORMAT_RGBX_8888: 349 case HAL_PIXEL_FORMAT_RGBA_8888: 350 return 1; 351 default: 352 return 0; 353 } 354 } 355 356 static int is_BGR(IMG_native_handle_t *handle) 357 { 358 return is_BGR_format(handle->iFormat); 359 } 360 361 static int is_NV12(IMG_native_handle_t *handle) 362 { 363 switch(handle->iFormat) 364 { 365 case HAL_PIXEL_FORMAT_TI_NV12: 366 case HAL_PIXEL_FORMAT_TI_NV12_PADDED: 367 return 1; 368 default: 369 return 0; 370 } 371 } 372 373 static int dockable(hwc_layer_t *layer) 374 { 375 IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; 376 377 return (handle->usage & GRALLOC_USAGE_EXTERNAL_DISP); 378 } 379 380 static unsigned int mem1d(IMG_native_handle_t *handle) 381 { 382 if (handle == NULL || is_NV12(handle)) 383 return 0; 384 385 int bpp = handle->iFormat == HAL_PIXEL_FORMAT_RGB_565 ? 2 : 4; 386 int stride = ALIGN(handle->iWidth, HW_ALIGN) * bpp; 387 return stride * handle->iHeight; 388 } 389 390 static void 391 omap4_hwc_setup_layer_base(struct dss2_ovl_cfg *oc, int index, int format, int blended, int width, int height) 392 { 393 unsigned int bits_per_pixel; 394 395 /* YUV2RGB conversion */ 396 const struct omap_dss_cconv_coefs ctbl_bt601_5 = { 397 298, 409, 0, 298, -208, -100, 298, 0, 517, 0, 398 }; 399 400 /* convert color format */ 401 switch (format) { 402 case HAL_PIXEL_FORMAT_RGBA_8888: 403 case HAL_PIXEL_FORMAT_BGRA_8888: 404 oc->color_mode = OMAP_DSS_COLOR_ARGB32; 405 bits_per_pixel = 32; 406 if (blended) 407 break; 408 409 case HAL_PIXEL_FORMAT_RGBX_8888: 410 case HAL_PIXEL_FORMAT_BGRX_8888: 411 oc->color_mode = OMAP_DSS_COLOR_RGB24U; 412 bits_per_pixel = 32; 413 break; 414 415 case HAL_PIXEL_FORMAT_RGB_565: 416 oc->color_mode = OMAP_DSS_COLOR_RGB16; 417 bits_per_pixel = 16; 418 break; 419 420 case HAL_PIXEL_FORMAT_TI_NV12: 421 case HAL_PIXEL_FORMAT_TI_NV12_PADDED: 422 oc->color_mode = OMAP_DSS_COLOR_NV12; 423 bits_per_pixel = 8; 424 oc->cconv = ctbl_bt601_5; 425 break; 426 427 default: 428 /* Should have been filtered out */ 429 ALOGV("Unsupported pixel format"); 430 return; 431 } 432 433 oc->width = width; 434 oc->height = height; 435 oc->stride = ALIGN(width, HW_ALIGN) * bits_per_pixel / 8; 436 437 oc->enabled = 1; 438 oc->global_alpha = 255; 439 oc->zorder = index; 440 oc->ix = 0; 441 442 /* defaults for SGX framebuffer renders */ 443 oc->crop.w = oc->win.w = width; 444 oc->crop.h = oc->win.h = height; 445 446 /* for now interlacing and vc1 info is not supplied */ 447 oc->ilace = OMAP_DSS_ILACE_NONE; 448 oc->vc1.enable = 0; 449 } 450 451 static void 452 omap4_hwc_setup_layer(omap4_hwc_device_t *hwc_dev, struct dss2_ovl_info *ovl, 453 hwc_layer_t *layer, int index, 454 int format, int width, int height) 455 { 456 struct dss2_ovl_cfg *oc = &ovl->cfg; 457 458 //dump_layer(layer); 459 460 omap4_hwc_setup_layer_base(oc, index, format, is_BLENDED(layer), width, height); 461 462 /* convert transformation - assuming 0-set config */ 463 if (layer->transform & HWC_TRANSFORM_FLIP_H) 464 oc->mirror = 1; 465 if (layer->transform & HWC_TRANSFORM_FLIP_V) { 466 oc->rotation = 2; 467 oc->mirror = !oc->mirror; 468 } 469 if (layer->transform & HWC_TRANSFORM_ROT_90) { 470 oc->rotation += oc->mirror ? -1 : 1; 471 oc->rotation &= 3; 472 } 473 474 oc->pre_mult_alpha = layer->blending == HWC_BLENDING_PREMULT; 475 476 /* display position */ 477 oc->win.x = layer->displayFrame.left; 478 oc->win.y = layer->displayFrame.top; 479 oc->win.w = WIDTH(layer->displayFrame); 480 oc->win.h = HEIGHT(layer->displayFrame); 481 482 /* crop */ 483 oc->crop.x = layer->sourceCrop.left; 484 oc->crop.y = layer->sourceCrop.top; 485 oc->crop.w = WIDTH(layer->sourceCrop); 486 oc->crop.h = HEIGHT(layer->sourceCrop); 487 } 488 489 const float m_unit[2][3] = { { 1., 0., 0. }, { 0., 1., 0. } }; 490 491 static inline void m_translate(float m[2][3], int dx, int dy) 492 { 493 m[0][2] += dx; 494 m[1][2] += dy; 495 } 496 497 static inline void m_scale1(float m[3], int from, int to) 498 { 499 m[0] = m[0] * to / from; 500 m[1] = m[1] * to / from; 501 m[2] = m[2] * to / from; 502 } 503 504 static inline void m_scale(float m[2][3], int x_from, int x_to, int y_from, int y_to) 505 { 506 m_scale1(m[0], x_from, x_to); 507 m_scale1(m[1], y_from, y_to); 508 } 509 510 static void m_rotate(float m[2][3], int quarter_turns) 511 { 512 if (quarter_turns & 2) 513 m_scale(m, 1, -1, 1, -1); 514 if (quarter_turns & 1) { 515 int q; 516 q = m[0][0]; m[0][0] = -m[1][0]; m[1][0] = q; 517 q = m[0][1]; m[0][1] = -m[1][1]; m[1][1] = q; 518 q = m[0][2]; m[0][2] = -m[1][2]; m[1][2] = q; 519 } 520 } 521 522 static inline int m_round(float x) 523 { 524 /* int truncates towards 0 */ 525 return (int) (x < 0 ? x - 0.5 : x + 0.5); 526 } 527 528 /* 529 * assuming xpy (xratio:yratio) original pixel ratio, calculate the adjusted width 530 * and height for a screen of xres/yres and physical size of width/height. 531 * The adjusted size is the largest that fits into the screen. 532 */ 533 static void get_max_dimensions(__u32 orig_xres, __u32 orig_yres, 534 float xpy, 535 __u32 scr_xres, __u32 scr_yres, 536 __u32 scr_width, __u32 scr_height, 537 __u32 *adj_xres, __u32 *adj_yres) 538 { 539 /* assume full screen (largest size)*/ 540 *adj_xres = scr_xres; 541 *adj_yres = scr_yres; 542 543 /* assume 1:1 pixel ratios if none supplied */ 544 if (!scr_width || !scr_height) { 545 scr_width = scr_xres; 546 scr_height = scr_yres; 547 } 548 549 /* trim to keep aspect ratio */ 550 float x_factor = orig_xres * xpy * scr_height; 551 float y_factor = orig_yres * scr_width; 552 553 /* allow for tolerance so we avoid scaling if framebuffer is standard size */ 554 if (x_factor < y_factor * (1.f - ASPECT_RATIO_TOLERANCE)) 555 *adj_xres = (__u32) (x_factor * *adj_xres / y_factor + 0.5); 556 else if (x_factor * (1.f - ASPECT_RATIO_TOLERANCE) > y_factor) 557 *adj_yres = (__u32) (y_factor * *adj_yres / x_factor + 0.5); 558 } 559 560 static void set_ext_matrix(omap4_hwc_ext_t *ext, struct hwc_rect region) 561 { 562 int orig_w = WIDTH(region); 563 int orig_h = HEIGHT(region); 564 float xpy = ext->lcd_xpy; 565 566 /* reorientation matrix is: 567 m = (center-from-target-center) * (scale-to-target) * (mirror) * (rotate) * (center-to-original-center) */ 568 569 memcpy(ext->m, m_unit, sizeof(m_unit)); 570 m_translate(ext->m, -(orig_w >> 1) - region.left, -(orig_h >> 1) - region.top); 571 m_rotate(ext->m, ext->current.rotation); 572 if (ext->current.hflip) 573 m_scale(ext->m, 1, -1, 1, 1); 574 575 if (ext->current.rotation & 1) { 576 swap(orig_w, orig_h); 577 xpy = 1. / xpy; 578 } 579 580 /* get target size */ 581 __u32 adj_xres, adj_yres; 582 get_max_dimensions(orig_w, orig_h, xpy, 583 ext->xres, ext->yres, ext->width, ext->height, 584 &adj_xres, &adj_yres); 585 586 m_scale(ext->m, orig_w, adj_xres, orig_h, adj_yres); 587 m_translate(ext->m, ext->xres >> 1, ext->yres >> 1); 588 } 589 590 static int 591 crop_to_rect(struct dss2_ovl_cfg *cfg, struct hwc_rect vis_rect) 592 { 593 struct { 594 int xy[2]; 595 int wh[2]; 596 } crop, win; 597 struct { 598 int lt[2]; 599 int rb[2]; 600 } vis; 601 win.xy[0] = cfg->win.x; win.xy[1] = cfg->win.y; 602 win.wh[0] = cfg->win.w; win.wh[1] = cfg->win.h; 603 crop.xy[0] = cfg->crop.x; crop.xy[1] = cfg->crop.y; 604 crop.wh[0] = cfg->crop.w; crop.wh[1] = cfg->crop.h; 605 vis.lt[0] = vis_rect.left; vis.lt[1] = vis_rect.top; 606 vis.rb[0] = vis_rect.right; vis.rb[1] = vis_rect.bottom; 607 608 int c, swap = cfg->rotation & 1; 609 610 /* align crop window with display coordinates */ 611 if (swap) 612 crop.xy[1] -= (crop.wh[1] = -crop.wh[1]); 613 if (cfg->rotation & 2) 614 crop.xy[!swap] -= (crop.wh[!swap] = -crop.wh[!swap]); 615 if ((!cfg->mirror) ^ !(cfg->rotation & 2)) 616 crop.xy[swap] -= (crop.wh[swap] = -crop.wh[swap]); 617 618 for (c = 0; c < 2; c++) { 619 /* see if complete buffer is outside the vis or it is 620 fully cropped or scaled to 0 */ 621 if (win.wh[c] <= 0 || vis.rb[c] <= vis.lt[c] || 622 win.xy[c] + win.wh[c] <= vis.lt[c] || 623 win.xy[c] >= vis.rb[c] || 624 !crop.wh[c ^ swap]) 625 return -ENOENT; 626 627 /* crop left/top */ 628 if (win.xy[c] < vis.lt[c]) { 629 /* correction term */ 630 int a = (vis.lt[c] - win.xy[c]) * crop.wh[c ^ swap] / win.wh[c]; 631 crop.xy[c ^ swap] += a; 632 crop.wh[c ^ swap] -= a; 633 win.wh[c] -= vis.lt[c] - win.xy[c]; 634 win.xy[c] = vis.lt[c]; 635 } 636 /* crop right/bottom */ 637 if (win.xy[c] + win.wh[c] > vis.rb[c]) { 638 crop.wh[c ^ swap] = crop.wh[c ^ swap] * (vis.rb[c] - win.xy[c]) / win.wh[c]; 639 win.wh[c] = vis.rb[c] - win.xy[c]; 640 } 641 642 if (!crop.wh[c ^ swap] || !win.wh[c]) 643 return -ENOENT; 644 } 645 646 /* realign crop window to buffer coordinates */ 647 if (cfg->rotation & 2) 648 crop.xy[!swap] -= (crop.wh[!swap] = -crop.wh[!swap]); 649 if ((!cfg->mirror) ^ !(cfg->rotation & 2)) 650 crop.xy[swap] -= (crop.wh[swap] = -crop.wh[swap]); 651 if (swap) 652 crop.xy[1] -= (crop.wh[1] = -crop.wh[1]); 653 654 cfg->win.x = win.xy[0]; cfg->win.y = win.xy[1]; 655 cfg->win.w = win.wh[0]; cfg->win.h = win.wh[1]; 656 cfg->crop.x = crop.xy[0]; cfg->crop.y = crop.xy[1]; 657 cfg->crop.w = crop.wh[0]; cfg->crop.h = crop.wh[1]; 658 659 return 0; 660 } 661 662 static void 663 omap4_hwc_adjust_ext_layer(omap4_hwc_ext_t *ext, struct dss2_ovl_info *ovl) 664 { 665 struct dss2_ovl_cfg *oc = &ovl->cfg; 666 float x, y, w, h; 667 668 /* crop to clone region if mirroring */ 669 if (!ext->current.docking && 670 crop_to_rect(&ovl->cfg, ext->mirror_region) != 0) { 671 ovl->cfg.enabled = 0; 672 return; 673 } 674 675 /* display position */ 676 x = ext->m[0][0] * oc->win.x + ext->m[0][1] * oc->win.y + ext->m[0][2]; 677 y = ext->m[1][0] * oc->win.x + ext->m[1][1] * oc->win.y + ext->m[1][2]; 678 w = ext->m[0][0] * oc->win.w + ext->m[0][1] * oc->win.h; 679 h = ext->m[1][0] * oc->win.w + ext->m[1][1] * oc->win.h; 680 oc->win.x = m_round(w > 0 ? x : x + w); 681 oc->win.y = m_round(h > 0 ? y : y + h); 682 oc->win.w = m_round(w > 0 ? w : -w); 683 oc->win.h = m_round(h > 0 ? h : -h); 684 685 /* combining transformations: F^a*R^b*F^i*R^j = F^(a+b)*R^(j+b*(-1)^i), because F*R = R^(-1)*F */ 686 oc->rotation += (oc->mirror ? -1 : 1) * ext->current.rotation; 687 oc->rotation &= 3; 688 if (ext->current.hflip) 689 oc->mirror = !oc->mirror; 690 } 691 692 static struct dsscomp_dispc_limitations { 693 __u8 max_xdecim_2d; 694 __u8 max_ydecim_2d; 695 __u8 max_xdecim_1d; 696 __u8 max_ydecim_1d; 697 __u32 fclk; 698 __u8 max_downscale; 699 __u8 min_width; 700 __u16 integer_scale_ratio_limit; 701 __u16 max_width; 702 __u16 max_height; 703 } limits = { 704 .max_xdecim_1d = 16, 705 .max_xdecim_2d = 16, 706 .max_ydecim_1d = 16, 707 .max_ydecim_2d = 2, 708 .fclk = 170666666, 709 .max_downscale = 4, 710 .min_width = 2, 711 .integer_scale_ratio_limit = 2048, 712 .max_width = 2048, 713 .max_height = 2048, 714 }; 715 716 static int omap4_hwc_can_scale(__u32 src_w, __u32 src_h, __u32 dst_w, __u32 dst_h, int is_2d, 717 struct dsscomp_display_info *dis, struct dsscomp_dispc_limitations *limits, 718 __u32 pclk) 719 { 720 __u32 fclk = limits->fclk / 1000; 721 __u32 min_src_w = DIV_ROUND_UP(src_w, is_2d ? limits->max_xdecim_2d : limits->max_xdecim_1d); 722 __u32 min_src_h = DIV_ROUND_UP(src_h, is_2d ? limits->max_ydecim_2d : limits->max_ydecim_1d); 723 724 /* ERRATAs */ 725 /* cannot render 1-width layers on DSI video mode panels - we just disallow all 1-width LCD layers */ 726 if (dis->channel != OMAP_DSS_CHANNEL_DIGIT && dst_w < limits->min_width) 727 return 0; 728 729 /* NOTE: no support for checking YUV422 layers that are tricky to scale */ 730 731 /* FIXME: limit vertical downscale well below theoretical limit as we saw display artifacts */ 732 if (dst_h < src_h / 4) 733 return 0; 734 735 /* max downscale */ 736 if (dst_h * limits->max_downscale < min_src_h) 737 return 0; 738 739 /* for manual panels pclk is 0, and there are no pclk based scaling limits */ 740 if (!pclk) 741 return !(dst_w * limits->max_downscale < min_src_w); 742 743 /* :HACK: limit horizontal downscale well below theoretical limit as we saw display artifacts */ 744 if (dst_w * 4 < src_w) 745 return 0; 746 747 /* max horizontal downscale is 4, or the fclk/pixclk */ 748 if (fclk > pclk * limits->max_downscale) 749 fclk = pclk * limits->max_downscale; 750 /* for small parts, we need to use integer fclk/pixclk */ 751 if (src_w < limits->integer_scale_ratio_limit) 752 fclk = fclk / pclk * pclk; 753 if ((__u32) dst_w * fclk < min_src_w * pclk) 754 return 0; 755 756 return 1; 757 } 758 759 static int omap4_hwc_can_scale_layer(omap4_hwc_device_t *hwc_dev, hwc_layer_t *layer, IMG_native_handle_t *handle) 760 { 761 int src_w = WIDTH(layer->sourceCrop); 762 int src_h = HEIGHT(layer->sourceCrop); 763 int dst_w = WIDTH(layer->displayFrame); 764 int dst_h = HEIGHT(layer->displayFrame); 765 766 /* account for 90-degree rotation */ 767 if (layer->transform & HWC_TRANSFORM_ROT_90) 768 swap(src_w, src_h); 769 770 /* NOTE: layers should be able to be scaled externally since 771 framebuffer is able to be scaled on selected external resolution */ 772 return omap4_hwc_can_scale(src_w, src_h, dst_w, dst_h, is_NV12(handle), &hwc_dev->fb_dis, &limits, 773 hwc_dev->fb_dis.timings.pixel_clock); 774 } 775 776 static int omap4_hwc_is_valid_layer(omap4_hwc_device_t *hwc_dev, 777 hwc_layer_t *layer, 778 IMG_native_handle_t *handle) 779 { 780 /* Skip layers are handled by SF */ 781 if ((layer->flags & HWC_SKIP_LAYER) || !handle) 782 return 0; 783 784 if (!omap4_hwc_is_valid_format(handle->iFormat)) 785 return 0; 786 787 /* 1D buffers: no transform, must fit in TILER slot */ 788 if (!is_NV12(handle)) { 789 if (layer->transform) 790 return 0; 791 if (mem1d(handle) > MAX_TILER_SLOT) 792 return 0; 793 } 794 795 return omap4_hwc_can_scale_layer(hwc_dev, layer, handle); 796 } 797 798 static __u32 add_scaling_score(__u32 score, 799 __u32 xres, __u32 yres, __u32 refresh, 800 __u32 ext_xres, __u32 ext_yres, 801 __u32 mode_xres, __u32 mode_yres, __u32 mode_refresh) 802 { 803 __u32 area = xres * yres; 804 __u32 ext_area = ext_xres * ext_yres; 805 __u32 mode_area = mode_xres * mode_yres; 806 807 /* prefer to upscale (1% tolerance) [0..1] (insert after 1st bit) */ 808 int upscale = (ext_xres >= xres * 99 / 100 && ext_yres >= yres * 99 / 100); 809 score = (((score & ~1) | upscale) << 1) | (score & 1); 810 811 /* pick minimum scaling [0..16] */ 812 if (ext_area > area) 813 score = (score << 5) | (16 * area / ext_area); 814 else 815 score = (score << 5) | (16 * ext_area / area); 816 817 /* pick smallest leftover area [0..16] */ 818 score = (score << 5) | ((16 * ext_area + (mode_area >> 1)) / mode_area); 819 820 /* adjust mode refresh rate */ 821 mode_refresh += mode_refresh % 6 == 5; 822 823 /* prefer same or higher frame rate */ 824 upscale = (mode_refresh >= refresh); 825 score = (score << 1) | upscale; 826 827 /* pick closest frame rate */ 828 if (mode_refresh > refresh) 829 score = (score << 8) | (240 * refresh / mode_refresh); 830 else 831 score = (score << 8) | (240 * mode_refresh / refresh); 832 833 return score; 834 } 835 836 static int omap4_hwc_set_best_hdmi_mode(omap4_hwc_device_t *hwc_dev, __u32 xres, __u32 yres, 837 float xpy) 838 { 839 struct _qdis { 840 struct dsscomp_display_info dis; 841 struct dsscomp_videomode modedb[32]; 842 } d = { .dis = { .ix = 1 } }; 843 omap4_hwc_ext_t *ext = &hwc_dev->ext; 844 845 d.dis.modedb_len = sizeof(d.modedb) / sizeof(*d.modedb); 846 int ret = ioctl(hwc_dev->dsscomp_fd, DSSCIOC_QUERY_DISPLAY, &d); 847 if (ret) 848 return ret; 849 850 if (d.dis.timings.x_res * d.dis.timings.y_res == 0 || 851 xres * yres == 0) 852 return -EINVAL; 853 854 __u32 i, best = ~0, best_score = 0; 855 ext->width = d.dis.width_in_mm; 856 ext->height = d.dis.height_in_mm; 857 ext->xres = d.dis.timings.x_res; 858 ext->yres = d.dis.timings.y_res; 859 860 /* use VGA external resolution as default */ 861 if (!ext->xres || !ext->yres) { 862 ext->xres = 640; 863 ext->yres = 480; 864 } 865 866 __u32 ext_fb_xres, ext_fb_yres; 867 for (i = 0; i < d.dis.modedb_len; i++) { 868 __u32 score = 0; 869 __u32 mode_xres = d.modedb[i].xres; 870 __u32 mode_yres = d.modedb[i].yres; 871 __u32 ext_width = d.dis.width_in_mm; 872 __u32 ext_height = d.dis.height_in_mm; 873 874 if (d.modedb[i].flag & FB_FLAG_RATIO_4_3) { 875 ext_width = 4; 876 ext_height = 3; 877 } else if (d.modedb[i].flag & FB_FLAG_RATIO_16_9) { 878 ext_width = 16; 879 ext_height = 9; 880 } 881 882 if (!mode_xres || !mode_yres) 883 continue; 884 885 get_max_dimensions(xres, yres, xpy, mode_xres, mode_yres, 886 ext_width, ext_height, &ext_fb_xres, &ext_fb_yres); 887 888 /* we need to ensure that even TILER2D buffers can be scaled */ 889 if (!d.modedb[i].pixclock || 890 d.modedb[i].vmode || 891 !omap4_hwc_can_scale(xres, yres, ext_fb_xres, ext_fb_yres, 892 1, &d.dis, &limits, 893 1000000000 / d.modedb[i].pixclock)) 894 continue; 895 896 /* prefer CEA modes */ 897 if (d.modedb[i].flag & (FB_FLAG_RATIO_4_3 | FB_FLAG_RATIO_16_9)) 898 score = 1; 899 900 /* prefer the same mode as we use for mirroring to avoid mode change */ 901 score = (score << 1) | (i == ~ext->mirror_mode && ext->avoid_mode_change); 902 903 score = add_scaling_score(score, xres, yres, 60, ext_fb_xres, ext_fb_yres, 904 mode_xres, mode_yres, d.modedb[i].refresh ? : 1); 905 906 ALOGD("#%d: %dx%d %dHz", i, mode_xres, mode_yres, d.modedb[i].refresh); 907 if (debug) 908 ALOGD(" score=0x%x adj.res=%dx%d", score, ext_fb_xres, ext_fb_yres); 909 if (best_score < score) { 910 ext->width = ext_width; 911 ext->height = ext_height; 912 ext->xres = mode_xres; 913 ext->yres = mode_yres; 914 best = i; 915 best_score = score; 916 } 917 } 918 if (~best) { 919 struct dsscomp_setup_display_data sdis = { .ix = 1, }; 920 sdis.mode = d.dis.modedb[best]; 921 ALOGD("picking #%d", best); 922 /* only reconfigure on change */ 923 if (ext->last_mode != ~best) 924 ioctl(hwc_dev->dsscomp_fd, DSSCIOC_SETUP_DISPLAY, &sdis); 925 ext->last_mode = ~best; 926 } else { 927 __u32 ext_width = d.dis.width_in_mm; 928 __u32 ext_height = d.dis.height_in_mm; 929 __u32 ext_fb_xres, ext_fb_yres; 930 931 get_max_dimensions(xres, yres, xpy, d.dis.timings.x_res, d.dis.timings.y_res, 932 ext_width, ext_height, &ext_fb_xres, &ext_fb_yres); 933 if (!d.dis.timings.pixel_clock || 934 d.dis.mgr.interlaced || 935 !omap4_hwc_can_scale(xres, yres, ext_fb_xres, ext_fb_yres, 936 1, &d.dis, &limits, 937 d.dis.timings.pixel_clock)) { 938 ALOGW("DSS scaler cannot support HDMI cloning"); 939 return -1; 940 } 941 } 942 ext->last_xres_used = xres; 943 ext->last_yres_used = yres; 944 ext->last_xpy = xpy; 945 if (d.dis.channel == OMAP_DSS_CHANNEL_DIGIT) 946 ext->on_tv = 1; 947 return 0; 948 } 949 950 struct counts { 951 unsigned int possible_overlay_layers; 952 unsigned int composited_layers; 953 unsigned int scaled_layers; 954 unsigned int RGB; 955 unsigned int BGR; 956 unsigned int NV12; 957 unsigned int dockable; 958 unsigned int protected; 959 960 unsigned int max_hw_overlays; 961 unsigned int max_scaling_overlays; 962 unsigned int mem; 963 }; 964 965 static void gather_layer_statistics(omap4_hwc_device_t *hwc_dev, struct counts *num, hwc_layer_list_t *list) 966 { 967 unsigned int i; 968 969 /* Figure out how many layers we can support via DSS */ 970 for (i = 0; list && i < list->numHwLayers; i++) { 971 hwc_layer_t *layer = &list->hwLayers[i]; 972 IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; 973 974 layer->compositionType = HWC_FRAMEBUFFER; 975 976 if (omap4_hwc_is_valid_layer(hwc_dev, layer, handle)) { 977 num->possible_overlay_layers++; 978 979 /* NV12 layers can only be rendered on scaling overlays */ 980 if (scaled(layer) || is_NV12(handle)) 981 num->scaled_layers++; 982 983 if (is_BGR(handle)) 984 num->BGR++; 985 else if (is_RGB(handle)) 986 num->RGB++; 987 else if (is_NV12(handle)) 988 num->NV12++; 989 990 if (dockable(layer)) 991 num->dockable++; 992 993 if (is_protected(layer)) 994 num->protected++; 995 996 num->mem += mem1d(handle); 997 } 998 } 999 } 1000 1001 static void decide_supported_cloning(omap4_hwc_device_t *hwc_dev, struct counts *num) 1002 { 1003 omap4_hwc_ext_t *ext = &hwc_dev->ext; 1004 int nonscaling_ovls = NUM_NONSCALING_OVERLAYS; 1005 num->max_hw_overlays = MAX_HW_OVERLAYS; 1006 1007 /* 1008 * We cannot atomically switch overlays from one display to another. First, they 1009 * have to be disabled, and the disabling has to take effect on the current display. 1010 * We keep track of the available number of overlays here. 1011 */ 1012 if (ext->dock.enabled && !(ext->mirror.enabled && !(num->dockable || ext->force_dock))) { 1013 /* some overlays may already be used by the external display, so we account for this */ 1014 1015 /* reserve just a video pipeline for HDMI if docking */ 1016 hwc_dev->ext_ovls = (num->dockable || ext->force_dock) ? 1 : 0; 1017 num->max_hw_overlays -= max(hwc_dev->ext_ovls, hwc_dev->last_ext_ovls); 1018 1019 /* use mirroring transform if we are auto-switching to docking mode while mirroring*/ 1020 if (ext->mirror.enabled) { 1021 ext->current = ext->mirror; 1022 ext->current.docking = 1; 1023 } else { 1024 ext->current = ext->dock; 1025 } 1026 } else if (ext->mirror.enabled) { 1027 /* 1028 * otherwise, manage just from half the pipelines. NOTE: there is 1029 * no danger of having used too many overlays for external display here. 1030 */ 1031 num->max_hw_overlays >>= 1; 1032 nonscaling_ovls >>= 1; 1033 hwc_dev->ext_ovls = MAX_HW_OVERLAYS - num->max_hw_overlays; 1034 ext->current = ext->mirror; 1035 } else { 1036 num->max_hw_overlays -= hwc_dev->last_ext_ovls; 1037 hwc_dev->ext_ovls = 0; 1038 ext->current.enabled = 0; 1039 } 1040 1041 /* 1042 * :TRICKY: We may not have enough overlays on the external display. We "reserve" them 1043 * here to figure out if mirroring is supported, but may not do mirroring for the first 1044 * frame while the overlays required for it are cleared. 1045 */ 1046 hwc_dev->ext_ovls_wanted = hwc_dev->ext_ovls; 1047 hwc_dev->ext_ovls = min(MAX_HW_OVERLAYS - hwc_dev->last_int_ovls, hwc_dev->ext_ovls); 1048 1049 /* if mirroring, we are limited by both internal and external overlays. However, 1050 ext_ovls is always <= MAX_HW_OVERLAYS / 2 <= max_hw_overlays */ 1051 if (hwc_dev->ext_ovls && ext->current.enabled && !ext->current.docking) 1052 num->max_hw_overlays = hwc_dev->ext_ovls; 1053 1054 num->max_scaling_overlays = num->max_hw_overlays - nonscaling_ovls; 1055 } 1056 1057 static int can_dss_render_all(omap4_hwc_device_t *hwc_dev, struct counts *num) 1058 { 1059 omap4_hwc_ext_t *ext = &hwc_dev->ext; 1060 int on_tv = ext->on_tv && ext->current.enabled; 1061 int tform = ext->current.enabled && (ext->current.rotation || ext->current.hflip); 1062 1063 return !hwc_dev->force_sgx && 1064 /* must have at least one layer if using composition bypass to get sync object */ 1065 num->possible_overlay_layers && 1066 num->possible_overlay_layers <= num->max_hw_overlays && 1067 num->possible_overlay_layers == num->composited_layers && 1068 num->scaled_layers <= num->max_scaling_overlays && 1069 num->NV12 <= num->max_scaling_overlays && 1070 /* fits into TILER slot */ 1071 num->mem <= MAX_TILER_SLOT && 1072 /* we cannot clone non-NV12 transformed layers */ 1073 (!tform || num->NV12 == num->possible_overlay_layers) && 1074 /* HDMI cannot display BGR */ 1075 (num->BGR == 0 || (num->RGB == 0 && !on_tv) || !hwc_dev->flags_rgb_order); 1076 } 1077 1078 static inline int can_dss_render_layer(omap4_hwc_device_t *hwc_dev, 1079 hwc_layer_t *layer) 1080 { 1081 IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; 1082 1083 omap4_hwc_ext_t *ext = &hwc_dev->ext; 1084 int on_tv = ext->on_tv && ext->current.enabled; 1085 int tform = ext->current.enabled && (ext->current.rotation || ext->current.hflip); 1086 1087 return omap4_hwc_is_valid_layer(hwc_dev, layer, handle) && 1088 /* cannot rotate non-NV12 layers on external display */ 1089 (!tform || is_NV12(handle)) && 1090 /* skip non-NV12 layers if also using SGX (if nv12_only flag is set) */ 1091 (!hwc_dev->flags_nv12_only || (!hwc_dev->use_sgx || is_NV12(handle))) && 1092 /* make sure RGB ordering is consistent (if rgb_order flag is set) */ 1093 (!(hwc_dev->swap_rb ? is_RGB(handle) : is_BGR(handle)) || 1094 !hwc_dev->flags_rgb_order) && 1095 /* TV can only render RGB */ 1096 !(on_tv && is_BGR(handle)); 1097 } 1098 1099 static inline int display_area(struct dss2_ovl_info *o) 1100 { 1101 return o->cfg.win.w * o->cfg.win.h; 1102 } 1103 1104 static int clone_layer(omap4_hwc_device_t *hwc_dev, int ix) { 1105 struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->dsscomp_data; 1106 omap4_hwc_ext_t *ext = &hwc_dev->ext; 1107 int ext_ovl_ix = dsscomp->num_ovls - hwc_dev->post2_layers; 1108 struct dss2_ovl_info *o = &dsscomp->ovls[dsscomp->num_ovls]; 1109 1110 if (dsscomp->num_ovls >= MAX_HW_OVERLAYS) { 1111 ALOGE("**** cannot clone layer #%d. using all %d overlays.", ix, dsscomp->num_ovls); 1112 return -EBUSY; 1113 } 1114 1115 memcpy(o, dsscomp->ovls + ix, sizeof(*o)); 1116 1117 /* reserve overlays at end for other display */ 1118 o->cfg.ix = MAX_HW_OVERLAYS - 1 - ext_ovl_ix; 1119 o->cfg.mgr_ix = 1; 1120 o->addressing = OMAP_DSS_BUFADDR_OVL_IX; 1121 o->ba = ix; 1122 1123 /* use distinct z values (to simplify z-order checking) */ 1124 o->cfg.zorder += hwc_dev->post2_layers; 1125 1126 omap4_hwc_adjust_ext_layer(&hwc_dev->ext, o); 1127 dsscomp->num_ovls++; 1128 return 0; 1129 } 1130 1131 static int clone_external_layer(omap4_hwc_device_t *hwc_dev, int ix) { 1132 struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->dsscomp_data; 1133 omap4_hwc_ext_t *ext = &hwc_dev->ext; 1134 1135 /* mirror only 1 external layer */ 1136 struct dss2_ovl_info *o = &dsscomp->ovls[ix]; 1137 1138 /* full screen video after transformation */ 1139 __u32 xres = o->cfg.crop.w, yres = o->cfg.crop.h; 1140 if ((ext->current.rotation + o->cfg.rotation) & 1) 1141 swap(xres, yres); 1142 float xpy = ext->lcd_xpy * o->cfg.win.w / o->cfg.win.h; 1143 if (o->cfg.rotation & 1) 1144 xpy = o->cfg.crop.h / xpy / o->cfg.crop.w; 1145 else 1146 xpy = o->cfg.crop.h * xpy / o->cfg.crop.w; 1147 if (ext->current.rotation & 1) 1148 xpy = 1. / xpy; 1149 1150 /* adjust hdmi mode based on resolution */ 1151 if (xres != ext->last_xres_used || 1152 yres != ext->last_yres_used || 1153 xpy < ext->last_xpy * (1.f - ASPECT_RATIO_TOLERANCE) || 1154 xpy * (1.f - ASPECT_RATIO_TOLERANCE) > ext->last_xpy) { 1155 ALOGD("set up HDMI for %d*%d\n", xres, yres); 1156 if (omap4_hwc_set_best_hdmi_mode(hwc_dev, xres, yres, xpy)) { 1157 ext->current.enabled = 0; 1158 return -ENODEV; 1159 } 1160 } 1161 1162 struct hwc_rect region = { 1163 .left = o->cfg.win.x, .top = o->cfg.win.y, 1164 .right = o->cfg.win.x + o->cfg.win.w, 1165 .bottom = o->cfg.win.y + o->cfg.win.h 1166 }; 1167 set_ext_matrix(&hwc_dev->ext, region); 1168 1169 return clone_layer(hwc_dev, ix); 1170 } 1171 1172 static int setup_mirroring(omap4_hwc_device_t *hwc_dev) 1173 { 1174 omap4_hwc_ext_t *ext = &hwc_dev->ext; 1175 1176 __u32 xres = WIDTH(ext->mirror_region); 1177 __u32 yres = HEIGHT(ext->mirror_region); 1178 if (ext->current.rotation & 1) 1179 swap(xres, yres); 1180 if (omap4_hwc_set_best_hdmi_mode(hwc_dev, xres, yres, ext->lcd_xpy)) 1181 return -ENODEV; 1182 set_ext_matrix(ext, ext->mirror_region); 1183 return 0; 1184 } 1185 1186 static int omap4_hwc_prepare(struct hwc_composer_device *dev, hwc_layer_list_t* list) 1187 { 1188 omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev; 1189 struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->dsscomp_data; 1190 struct counts num = { .composited_layers = list ? list->numHwLayers : 0 }; 1191 unsigned int i, ix; 1192 1193 pthread_mutex_lock(&hwc_dev->lock); 1194 memset(dsscomp, 0x0, sizeof(*dsscomp)); 1195 dsscomp->sync_id = sync_id++; 1196 1197 gather_layer_statistics(hwc_dev, &num, list); 1198 1199 decide_supported_cloning(hwc_dev, &num); 1200 1201 /* Disable the forced SGX rendering if there is only one layer */ 1202 if (hwc_dev->force_sgx && num.composited_layers <= 1) 1203 hwc_dev->force_sgx = 0; 1204 1205 /* phase 3 logic */ 1206 if (can_dss_render_all(hwc_dev, &num)) { 1207 /* All layers can be handled by the DSS -- don't use SGX for composition */ 1208 hwc_dev->use_sgx = 0; 1209 hwc_dev->swap_rb = num.BGR != 0; 1210 } else { 1211 /* Use SGX for composition plus first 3 layers that are DSS renderable */ 1212 hwc_dev->use_sgx = 1; 1213 hwc_dev->swap_rb = is_BGR_format(hwc_dev->fb_dev->base.format); 1214 } 1215 1216 /* setup pipes */ 1217 dsscomp->num_ovls = hwc_dev->use_sgx; 1218 int z = 0; 1219 int fb_z = -1; 1220 int scaled_gfx = 0; 1221 int ix_docking = -1; 1222 1223 /* set up if DSS layers */ 1224 unsigned int mem_used = 0; 1225 hwc_dev->ovls_blending = 0; 1226 for (i = 0; list && i < list->numHwLayers; i++) { 1227 hwc_layer_t *layer = &list->hwLayers[i]; 1228 IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; 1229 1230 if (dsscomp->num_ovls < num.max_hw_overlays && 1231 can_dss_render_layer(hwc_dev, layer) && 1232 (!hwc_dev->force_sgx || 1233 /* render protected and dockable layers via DSS */ 1234 is_protected(layer) || 1235 (hwc_dev->ext.current.docking && hwc_dev->ext.current.enabled && dockable(layer))) && 1236 mem_used + mem1d(handle) < MAX_TILER_SLOT && 1237 /* can't have a transparent overlay in the middle of the framebuffer stack */ 1238 !(is_BLENDED(layer) && fb_z >= 0)) { 1239 1240 /* render via DSS overlay */ 1241 mem_used += mem1d(handle); 1242 layer->compositionType = HWC_OVERLAY; 1243 1244 /* clear FB above all opaque layers if rendering via SGX */ 1245 if (hwc_dev->use_sgx && !is_BLENDED(layer)) 1246 layer->hints |= HWC_HINT_CLEAR_FB; 1247 /* see if any of the (non-backmost) overlays are doing blending */ 1248 else if (is_BLENDED(layer) && i > 0) 1249 hwc_dev->ovls_blending = 1; 1250 1251 hwc_dev->buffers[dsscomp->num_ovls] = layer->handle; 1252 1253 omap4_hwc_setup_layer(hwc_dev, 1254 &dsscomp->ovls[dsscomp->num_ovls], 1255 layer, 1256 z, 1257 handle->iFormat, 1258 handle->iWidth, 1259 handle->iHeight); 1260 1261 dsscomp->ovls[dsscomp->num_ovls].cfg.ix = dsscomp->num_ovls; 1262 dsscomp->ovls[dsscomp->num_ovls].addressing = OMAP_DSS_BUFADDR_LAYER_IX; 1263 dsscomp->ovls[dsscomp->num_ovls].ba = dsscomp->num_ovls; 1264 1265 /* ensure GFX layer is never scaled */ 1266 if (dsscomp->num_ovls == 0) { 1267 scaled_gfx = scaled(layer) || is_NV12(handle); 1268 } else if (scaled_gfx && !scaled(layer) && !is_NV12(handle)) { 1269 /* swap GFX layer with this one */ 1270 dsscomp->ovls[dsscomp->num_ovls].cfg.ix = 0; 1271 dsscomp->ovls[0].cfg.ix = dsscomp->num_ovls; 1272 scaled_gfx = 0; 1273 } 1274 1275 /* remember largest dockable layer */ 1276 if (dockable(layer) && 1277 (ix_docking < 0 || 1278 display_area(&dsscomp->ovls[dsscomp->num_ovls]) > display_area(&dsscomp->ovls[ix_docking]))) 1279 ix_docking = dsscomp->num_ovls; 1280 1281 dsscomp->num_ovls++; 1282 z++; 1283 } else if (hwc_dev->use_sgx) { 1284 if (fb_z < 0) { 1285 /* NOTE: we are not handling transparent cutout for now */ 1286 fb_z = z; 1287 z++; 1288 } else { 1289 /* move fb z-order up (by lowering dss layers) */ 1290 while (fb_z < z - 1) 1291 dsscomp->ovls[1 + fb_z++].cfg.zorder--; 1292 } 1293 } 1294 } 1295 1296 /* if scaling GFX (e.g. only 1 scaled surface) use a VID pipe */ 1297 if (scaled_gfx) 1298 dsscomp->ovls[0].cfg.ix = dsscomp->num_ovls; 1299 1300 if (hwc_dev->use_sgx) { 1301 /* assign a z-layer for fb */ 1302 if (fb_z < 0) { 1303 if (num.composited_layers) 1304 ALOGE("**** should have assigned z-layer for fb"); 1305 fb_z = z++; 1306 } 1307 1308 hwc_dev->buffers[0] = NULL; 1309 omap4_hwc_setup_layer_base(&dsscomp->ovls[0].cfg, fb_z, 1310 hwc_dev->fb_dev->base.format, 1311 1, /* FB is always premultiplied */ 1312 hwc_dev->fb_dev->base.width, 1313 hwc_dev->fb_dev->base.height); 1314 dsscomp->ovls[0].cfg.pre_mult_alpha = 1; 1315 dsscomp->ovls[0].addressing = OMAP_DSS_BUFADDR_LAYER_IX; 1316 dsscomp->ovls[0].ba = 0; 1317 } 1318 1319 /* mirror layers */ 1320 hwc_dev->post2_layers = dsscomp->num_ovls; 1321 1322 omap4_hwc_ext_t *ext = &hwc_dev->ext; 1323 if (ext->current.enabled && hwc_dev->ext_ovls) { 1324 if (ext->current.docking && ix_docking >= 0) { 1325 if (clone_external_layer(hwc_dev, ix_docking) == 0) 1326 dsscomp->ovls[dsscomp->num_ovls - 1].cfg.zorder = z++; 1327 } else if (ext->current.docking && ix_docking < 0 && ext->force_dock) { 1328 ix_docking = dsscomp->num_ovls; 1329 struct dss2_ovl_info *oi = &dsscomp->ovls[ix_docking]; 1330 omap4_hwc_setup_layer_base(&oi->cfg, 0, HAL_PIXEL_FORMAT_BGRA_8888, 1, 1331 dock_image.width, dock_image.height); 1332 oi->cfg.stride = dock_image.rowbytes; 1333 if (clone_external_layer(hwc_dev, ix_docking) == 0) { 1334 oi->addressing = OMAP_DSS_BUFADDR_FB; 1335 oi->ba = 0; 1336 z++; 1337 } 1338 } else if (!ext->current.docking) { 1339 int res = 0; 1340 1341 /* reset mode if we are coming from docking */ 1342 if (ext->last.docking) 1343 res = setup_mirroring(hwc_dev); 1344 1345 /* mirror all layers */ 1346 for (ix = 0; res == 0 && ix < hwc_dev->post2_layers; ix++) { 1347 if (clone_layer(hwc_dev, ix)) 1348 break; 1349 z++; 1350 } 1351 } 1352 } 1353 ext->last = ext->current; 1354 1355 if (z != dsscomp->num_ovls || dsscomp->num_ovls > MAX_HW_OVERLAYS) 1356 ALOGE("**** used %d z-layers for %d overlays\n", z, dsscomp->num_ovls); 1357 1358 /* verify all z-orders and overlay indices are distinct */ 1359 for (i = z = ix = 0; i < dsscomp->num_ovls; i++) { 1360 struct dss2_ovl_cfg *c = &dsscomp->ovls[i].cfg; 1361 1362 if (z & (1 << c->zorder)) 1363 ALOGE("**** used z-order #%d multiple times", c->zorder); 1364 if (ix & (1 << c->ix)) 1365 ALOGE("**** used ovl index #%d multiple times", c->ix); 1366 z |= 1 << c->zorder; 1367 ix |= 1 << c->ix; 1368 } 1369 dsscomp->mode = DSSCOMP_SETUP_DISPLAY; 1370 dsscomp->mgrs[0].ix = 0; 1371 dsscomp->mgrs[0].alpha_blending = 1; 1372 dsscomp->mgrs[0].swap_rb = hwc_dev->swap_rb; 1373 dsscomp->num_mgrs = 1; 1374 1375 if (ext->current.enabled || hwc_dev->last_ext_ovls) { 1376 dsscomp->mgrs[1] = dsscomp->mgrs[0]; 1377 dsscomp->mgrs[1].ix = 1; 1378 dsscomp->num_mgrs++; 1379 hwc_dev->ext_ovls = dsscomp->num_ovls - hwc_dev->post2_layers; 1380 } 1381 1382 if (debug) { 1383 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", 1384 dsscomp->sync_id, 1385 hwc_dev->use_sgx ? "SGX+OVL" : "all-OVL", 1386 num.composited_layers, 1387 num.possible_overlay_layers, num.scaled_layers, 1388 num.RGB, num.BGR, num.NV12, 1389 ext->on_tv ? "tv+" : "", 1390 ext->current.enabled ? ext->current.docking ? "dock+" : "mirror+" : "OFF+", 1391 ext->current.rotation * 90, 1392 ext->current.hflip ? "+hflip" : "", 1393 hwc_dev->ext_ovls, num.max_hw_overlays, hwc_dev->last_ext_ovls, hwc_dev->last_int_ovls); 1394 } 1395 1396 pthread_mutex_unlock(&hwc_dev->lock); 1397 return 0; 1398 } 1399 1400 static void omap4_hwc_reset_screen(omap4_hwc_device_t *hwc_dev) 1401 { 1402 static int first_set = 1; 1403 int ret; 1404 1405 if (first_set) { 1406 first_set = 0; 1407 struct dsscomp_setup_dispc_data d = { 1408 .num_mgrs = 1, 1409 }; 1410 /* remove bootloader image from the screen as blank/unblank does not change the composition */ 1411 ret = ioctl(hwc_dev->dsscomp_fd, DSSCIOC_SETUP_DISPC, &d); 1412 if (ret) 1413 ALOGW("failed to remove bootloader image"); 1414 1415 /* blank and unblank fd to make sure display is properly programmed on boot. 1416 * This is needed because the bootloader can not be trusted. 1417 */ 1418 ret = ioctl(hwc_dev->fb_fd, FBIOBLANK, FB_BLANK_POWERDOWN); 1419 if (ret) 1420 ALOGW("failed to blank display"); 1421 1422 ret = ioctl(hwc_dev->fb_fd, FBIOBLANK, FB_BLANK_UNBLANK); 1423 if (ret) 1424 ALOGW("failed to blank display"); 1425 } 1426 } 1427 1428 static int omap4_hwc_set(struct hwc_composer_device *dev, hwc_display_t dpy, 1429 hwc_surface_t sur, hwc_layer_list_t* list) 1430 { 1431 omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev; 1432 struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->dsscomp_data; 1433 int err = 0; 1434 int invalidate; 1435 1436 pthread_mutex_lock(&hwc_dev->lock); 1437 1438 omap4_hwc_reset_screen(hwc_dev); 1439 1440 invalidate = hwc_dev->ext_ovls_wanted && !hwc_dev->ext_ovls; 1441 1442 if (debug) 1443 dump_set_info(hwc_dev, list); 1444 1445 if (dpy && sur) { 1446 // list can be NULL which means hwc is temporarily disabled. 1447 // however, if dpy and sur are null it means we're turning the 1448 // screen off. no shall not call eglSwapBuffers() in that case. 1449 1450 if (hwc_dev->use_sgx) { 1451 if (!eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur)) { 1452 ALOGE("eglSwapBuffers error"); 1453 err = HWC_EGL_ERROR; 1454 goto err_out; 1455 } 1456 } 1457 1458 //dump_dsscomp(dsscomp); 1459 1460 // signal the event thread that a post has happened 1461 write(hwc_dev->pipe_fds[1], "s", 1); 1462 if (hwc_dev->force_sgx > 0) 1463 hwc_dev->force_sgx--; 1464 1465 err = hwc_dev->fb_dev->Post2((framebuffer_device_t *)hwc_dev->fb_dev, 1466 hwc_dev->buffers, 1467 hwc_dev->post2_layers, 1468 dsscomp, sizeof(*dsscomp)); 1469 } 1470 hwc_dev->last_ext_ovls = hwc_dev->ext_ovls; 1471 hwc_dev->last_int_ovls = hwc_dev->post2_layers; 1472 if (err) 1473 ALOGE("Post2 error"); 1474 1475 err_out: 1476 pthread_mutex_unlock(&hwc_dev->lock); 1477 1478 if (invalidate && hwc_dev->procs && hwc_dev->procs->invalidate) 1479 hwc_dev->procs->invalidate(hwc_dev->procs); 1480 1481 return err; 1482 } 1483 1484 static void omap4_hwc_dump(struct hwc_composer_device *dev, char *buff, int buff_len) 1485 { 1486 omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev; 1487 struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->dsscomp_data; 1488 struct dump_buf log = { 1489 .buf = buff, 1490 .buf_len = buff_len, 1491 }; 1492 int i; 1493 1494 dump_printf(&log, "omap4_hwc %d:\n", dsscomp->num_ovls); 1495 dump_printf(&log, " idle timeout: %dms\n", hwc_dev->idle); 1496 1497 for (i = 0; i < dsscomp->num_ovls; i++) { 1498 struct dss2_ovl_cfg *cfg = &dsscomp->ovls[i].cfg; 1499 1500 dump_printf(&log, " layer %d:\n", i); 1501 dump_printf(&log, " enabled: %s\n", 1502 cfg->enabled ? "true" : "false"); 1503 dump_printf(&log, " buff: %p %dx%d stride: %d\n", 1504 hwc_dev->buffers[i], cfg->width, cfg->height, cfg->stride); 1505 dump_printf(&log, " src: (%d,%d) %dx%d\n", 1506 cfg->crop.x, cfg->crop.y, cfg->crop.w, cfg->crop.h); 1507 dump_printf(&log, " dst: (%d,%d) %dx%d\n", 1508 cfg->win.x, cfg->win.y, cfg->win.w, cfg->win.h); 1509 dump_printf(&log, " ix: %d\n", cfg->ix); 1510 dump_printf(&log, " zorder: %d\n\n", cfg->zorder); 1511 } 1512 } 1513 1514 static void free_png_image(omap4_hwc_device_t *hwc_dev, struct omap4_hwc_img *img) 1515 { 1516 memset(img, 0, sizeof(*img)); 1517 } 1518 1519 static int load_png_image(omap4_hwc_device_t *hwc_dev, char *path, struct omap4_hwc_img *img) 1520 { 1521 void *ptr = NULL; 1522 png_bytepp row_pointers = NULL; 1523 1524 FILE *fd = fopen(path, "rb"); 1525 if (!fd) { 1526 ALOGE("failed to open PNG file %s: (%d)", path, errno); 1527 return -EINVAL; 1528 } 1529 1530 const int SIZE_PNG_HEADER = 8; 1531 __u8 header[SIZE_PNG_HEADER]; 1532 fread(header, 1, SIZE_PNG_HEADER, fd); 1533 if (png_sig_cmp(header, 0, SIZE_PNG_HEADER)) { 1534 ALOGE("%s is not a PNG file", path); 1535 goto fail; 1536 } 1537 1538 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 1539 if (!png_ptr) 1540 goto fail_alloc; 1541 png_infop info_ptr = png_create_info_struct(png_ptr); 1542 if (!info_ptr) 1543 goto fail_alloc; 1544 1545 if (setjmp(png_jmpbuf(png_ptr))) 1546 goto fail_alloc; 1547 1548 png_init_io(png_ptr, fd); 1549 png_set_sig_bytes(png_ptr, SIZE_PNG_HEADER); 1550 png_set_user_limits(png_ptr, limits.max_width, limits.max_height); 1551 png_read_info(png_ptr, info_ptr); 1552 1553 __u8 bit_depth = png_get_bit_depth(png_ptr, info_ptr); 1554 __u32 width = png_get_image_width(png_ptr, info_ptr); 1555 __u32 height = png_get_image_height(png_ptr, info_ptr); 1556 __u8 color_type = png_get_color_type(png_ptr, info_ptr); 1557 1558 switch (color_type) { 1559 case PNG_COLOR_TYPE_PALETTE: 1560 png_set_palette_to_rgb(png_ptr); 1561 png_set_filler(png_ptr, 128, PNG_FILLER_AFTER); 1562 break; 1563 case PNG_COLOR_TYPE_GRAY: 1564 if (bit_depth < 8) { 1565 png_set_expand_gray_1_2_4_to_8(png_ptr); 1566 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) 1567 png_set_tRNS_to_alpha(png_ptr); 1568 } else { 1569 png_set_filler(png_ptr, 128, PNG_FILLER_AFTER); 1570 } 1571 /* fall through */ 1572 case PNG_COLOR_TYPE_GRAY_ALPHA: 1573 png_set_gray_to_rgb(png_ptr); 1574 break; 1575 case PNG_COLOR_TYPE_RGB: 1576 png_set_filler(png_ptr, 128, PNG_FILLER_AFTER); 1577 /* fall through */ 1578 case PNG_COLOR_TYPE_RGB_ALPHA: 1579 png_set_bgr(png_ptr); 1580 break; 1581 default: 1582 ALOGE("unsupported PNG color: %x", color_type); 1583 goto fail_alloc; 1584 } 1585 1586 if (bit_depth == 16) 1587 png_set_strip_16(png_ptr); 1588 1589 const int bpp = 4; 1590 img->size = ALIGN(width * height * bpp, 4096); 1591 if (img->size > hwc_dev->img_mem_size) { 1592 ALOGE("image does not fit into framebuffer area (%d > %d)", img->size, hwc_dev->img_mem_size); 1593 goto fail_alloc; 1594 } 1595 img->ptr = hwc_dev->img_mem_ptr; 1596 1597 row_pointers = calloc(height, sizeof(*row_pointers)); 1598 if (!row_pointers) { 1599 ALOGE("failed to allocate row pointers"); 1600 goto fail_alloc; 1601 } 1602 __u32 i; 1603 for (i = 0; i < height; i++) 1604 row_pointers[i] = img->ptr + i * width * bpp; 1605 png_set_rows(png_ptr, info_ptr, row_pointers); 1606 png_read_update_info(png_ptr, info_ptr); 1607 img->rowbytes = png_get_rowbytes(png_ptr, info_ptr); 1608 1609 png_read_image(png_ptr, row_pointers); 1610 png_read_end(png_ptr, NULL); 1611 free(row_pointers); 1612 png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 1613 fclose(fd); 1614 img->width = width; 1615 img->height = height; 1616 return 0; 1617 1618 fail_alloc: 1619 free_png_image(hwc_dev, img); 1620 free(row_pointers); 1621 if (!png_ptr || !info_ptr) 1622 ALOGE("failed to allocate PNG structures"); 1623 png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 1624 fail: 1625 fclose(fd); 1626 return -EINVAL; 1627 } 1628 1629 1630 static int omap4_hwc_device_close(hw_device_t* device) 1631 { 1632 omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) device;; 1633 1634 if (hwc_dev) { 1635 if (hwc_dev->dsscomp_fd >= 0) 1636 close(hwc_dev->dsscomp_fd); 1637 if (hwc_dev->hdmi_fb_fd >= 0) 1638 close(hwc_dev->hdmi_fb_fd); 1639 if (hwc_dev->fb_fd >= 0) 1640 close(hwc_dev->fb_fd); 1641 /* pthread will get killed when parent process exits */ 1642 pthread_mutex_destroy(&hwc_dev->lock); 1643 free(hwc_dev); 1644 } 1645 1646 return 0; 1647 } 1648 1649 static int omap4_hwc_open_fb_hal(IMG_framebuffer_device_public_t **fb_dev) 1650 { 1651 const struct hw_module_t *psModule; 1652 IMG_gralloc_module_public_t *psGrallocModule; 1653 int err; 1654 1655 err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &psModule); 1656 psGrallocModule = (IMG_gralloc_module_public_t *) psModule; 1657 1658 if(err) 1659 goto err_out; 1660 1661 if (strcmp(psGrallocModule->base.common.author, "Imagination Technologies")) { 1662 err = -EINVAL; 1663 goto err_out; 1664 } 1665 1666 *fb_dev = psGrallocModule->psFrameBufferDevice; 1667 1668 return 0; 1669 1670 err_out: 1671 ALOGE("Composer HAL failed to load compatible Graphics HAL"); 1672 return err; 1673 } 1674 1675 static void handle_hotplug(omap4_hwc_device_t *hwc_dev) 1676 { 1677 omap4_hwc_ext_t *ext = &hwc_dev->ext; 1678 __u8 state = ext->hdmi_state; 1679 1680 pthread_mutex_lock(&hwc_dev->lock); 1681 ext->dock.enabled = ext->mirror.enabled = 0; 1682 if (state) { 1683 /* check whether we can clone and/or dock */ 1684 char value[PROPERTY_VALUE_MAX]; 1685 property_get("persist.hwc.docking.enabled", value, "1"); 1686 ext->dock.enabled = atoi(value) > 0; 1687 property_get("persist.hwc.mirroring.enabled", value, "1"); 1688 ext->mirror.enabled = atoi(value) > 0; 1689 property_get("persist.hwc.avoid_mode_change", value, "1"); 1690 ext->avoid_mode_change = atoi(value) > 0; 1691 1692 /* get cloning transformation */ 1693 property_get("persist.hwc.docking.transform", value, "0"); 1694 ext->dock.rotation = atoi(value) & EXT_ROTATION; 1695 ext->dock.hflip = (atoi(value) & EXT_HFLIP) > 0; 1696 ext->dock.docking = 1; 1697 property_get("persist.hwc.mirroring.transform", value, hwc_dev->fb_dev->base.height > hwc_dev->fb_dev->base.width ? "3" : "0"); 1698 ext->mirror.rotation = atoi(value) & EXT_ROTATION; 1699 ext->mirror.hflip = (atoi(value) & EXT_HFLIP) > 0; 1700 ext->mirror.docking = 0; 1701 1702 if (ext->force_dock) { 1703 /* restrict to docking with no transform */ 1704 ext->mirror.enabled = 0; 1705 ext->dock.rotation = 0; 1706 ext->dock.hflip = 0; 1707 1708 if (!dock_image.rowbytes) { 1709 property_get("persist.hwc.dock_image", value, "/vendor/res/images/dock/dock.png"); 1710 load_png_image(hwc_dev, value, &dock_image); 1711 } 1712 } 1713 1714 /* select best mode for mirroring */ 1715 if (ext->mirror.enabled) { 1716 ext->current = ext->mirror; 1717 ext->mirror_mode = 0; 1718 if (setup_mirroring(hwc_dev) == 0) { 1719 ext->mirror_mode = ext->last_mode; 1720 ioctl(hwc_dev->hdmi_fb_fd, FBIOBLANK, FB_BLANK_UNBLANK); 1721 } else 1722 ext->mirror.enabled = 0; 1723 } 1724 } else { 1725 ext->last_mode = 0; 1726 } 1727 ALOGI("external display changed (state=%d, mirror={%s tform=%ddeg%s}, dock={%s tform=%ddeg%s%s}, tv=%d", state, 1728 ext->mirror.enabled ? "enabled" : "disabled", 1729 ext->mirror.rotation * 90, 1730 ext->mirror.hflip ? "+hflip" : "", 1731 ext->dock.enabled ? "enabled" : "disabled", 1732 ext->dock.rotation * 90, 1733 ext->dock.hflip ? "+hflip" : "", 1734 ext->force_dock ? " forced" : "", 1735 ext->on_tv); 1736 1737 pthread_mutex_unlock(&hwc_dev->lock); 1738 1739 if (hwc_dev->procs && hwc_dev->procs->invalidate) 1740 hwc_dev->procs->invalidate(hwc_dev->procs); 1741 } 1742 1743 static void handle_uevents(omap4_hwc_device_t *hwc_dev, const char *buff, int len) 1744 { 1745 int dock; 1746 int hdmi; 1747 int vsync; 1748 int state = 0; 1749 uint64_t timestamp = 0; 1750 const char *s = buff; 1751 1752 dock = !strcmp(s, "change@/devices/virtual/switch/dock"); 1753 hdmi = !strcmp(s, "change@/devices/virtual/switch/hdmi"); 1754 vsync = !strcmp(s, "change@/devices/platform/omapfb") || 1755 !strcmp(s, "change@/devices/virtual/switch/omapfb-vsync"); 1756 1757 if (!dock && !vsync && !hdmi) 1758 return; 1759 1760 s += strlen(s) + 1; 1761 1762 while(*s) { 1763 if (!strncmp(s, "SWITCH_STATE=", strlen("SWITCH_STATE="))) 1764 state = atoi(s + strlen("SWITCH_STATE=")); 1765 else if (!strncmp(s, "SWITCH_TIME=", strlen("SWITCH_TIME="))) 1766 timestamp = strtoull(s + strlen("SWITCH_TIME="), NULL, 0); 1767 else if (!strncmp(s, "VSYNC=", strlen("VSYNC="))) 1768 timestamp = strtoull(s + strlen("VSYNC="), NULL, 0); 1769 1770 s += strlen(s) + 1; 1771 if (s - buff >= len) 1772 break; 1773 } 1774 1775 if (vsync) { 1776 if (hwc_dev->procs && hwc_dev->procs->vsync) { 1777 hwc_dev->procs->vsync(hwc_dev->procs, 0, timestamp); 1778 } 1779 } else { 1780 if (dock) 1781 hwc_dev->ext.force_dock = state == 1; 1782 else 1783 hwc_dev->ext.hdmi_state = state == 1; 1784 handle_hotplug(hwc_dev); 1785 } 1786 } 1787 1788 static void *omap4_hwc_hdmi_thread(void *data) 1789 { 1790 omap4_hwc_device_t *hwc_dev = data; 1791 static char uevent_desc[4096]; 1792 struct pollfd fds[2]; 1793 int invalidate = 0; 1794 int timeout; 1795 int err; 1796 1797 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY); 1798 1799 uevent_init(); 1800 1801 fds[0].fd = uevent_get_fd(); 1802 fds[0].events = POLLIN; 1803 fds[1].fd = hwc_dev->pipe_fds[0]; 1804 fds[1].events = POLLIN; 1805 1806 timeout = hwc_dev->idle ? hwc_dev->idle : -1; 1807 1808 memset(uevent_desc, 0, sizeof(uevent_desc)); 1809 1810 do { 1811 err = poll(fds, hwc_dev->idle ? 2 : 1, timeout); 1812 1813 if (err == 0) { 1814 if (hwc_dev->idle) { 1815 if (hwc_dev->procs && hwc_dev->procs->invalidate) { 1816 pthread_mutex_lock(&hwc_dev->lock); 1817 invalidate = !hwc_dev->force_sgx && hwc_dev->ovls_blending; 1818 if (invalidate) { 1819 hwc_dev->force_sgx = 2; 1820 } 1821 pthread_mutex_unlock(&hwc_dev->lock); 1822 1823 if (invalidate) { 1824 hwc_dev->procs->invalidate(hwc_dev->procs); 1825 timeout = -1; 1826 } 1827 } 1828 1829 continue; 1830 } 1831 } 1832 1833 if (err == -1) { 1834 if (errno != EINTR) 1835 ALOGE("event error: %m"); 1836 continue; 1837 } 1838 1839 if (hwc_dev->idle && fds[1].revents & POLLIN) { 1840 char c; 1841 read(hwc_dev->pipe_fds[0], &c, 1); 1842 if (!hwc_dev->force_sgx) 1843 timeout = hwc_dev->idle ? hwc_dev->idle : -1; 1844 } 1845 1846 if (fds[0].revents & POLLIN) { 1847 /* keep last 2 zeroes to ensure double 0 termination */ 1848 int len = uevent_next_event(uevent_desc, sizeof(uevent_desc) - 2); 1849 handle_uevents(hwc_dev, uevent_desc, len); 1850 } 1851 } while (1); 1852 1853 return NULL; 1854 } 1855 1856 static void omap4_hwc_registerProcs(struct hwc_composer_device* dev, 1857 hwc_procs_t const* procs) 1858 { 1859 omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) dev; 1860 1861 hwc_dev->procs = (typeof(hwc_dev->procs)) procs; 1862 } 1863 1864 static int omap4_hwc_query(struct hwc_composer_device* dev, 1865 int what, int* value) 1866 { 1867 omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) dev; 1868 1869 switch (what) { 1870 case HWC_BACKGROUND_LAYER_SUPPORTED: 1871 // we don't support the background layer yet 1872 value[0] = 0; 1873 break; 1874 case HWC_VSYNC_PERIOD: 1875 // vsync period in nanosecond 1876 value[0] = 1000000000.0 / hwc_dev->fb_dev->base.fps; 1877 break; 1878 default: 1879 // unsupported query 1880 return -EINVAL; 1881 } 1882 return 0; 1883 } 1884 1885 static int omap4_hwc_event_control(struct hwc_composer_device* dev, 1886 int event, int enabled) 1887 { 1888 omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) dev; 1889 1890 switch (event) { 1891 case HWC_EVENT_VSYNC: 1892 { 1893 int val = !!enabled; 1894 int err; 1895 1896 err = ioctl(hwc_dev->fb_fd, OMAPFB_ENABLEVSYNC, &val); 1897 if (err < 0) 1898 return -errno; 1899 1900 return 0; 1901 } 1902 default: 1903 return -EINVAL; 1904 } 1905 } 1906 1907 struct hwc_methods omap4_hwc_methods = { 1908 .eventControl = &omap4_hwc_event_control, 1909 }; 1910 1911 static int omap4_hwc_device_open(const hw_module_t* module, const char* name, 1912 hw_device_t** device) 1913 { 1914 omap4_hwc_module_t *hwc_mod = (omap4_hwc_module_t *)module; 1915 omap4_hwc_device_t *hwc_dev; 1916 int err = 0; 1917 1918 if (strcmp(name, HWC_HARDWARE_COMPOSER)) { 1919 return -EINVAL; 1920 } 1921 1922 if (!hwc_mod->fb_dev) { 1923 err = omap4_hwc_open_fb_hal(&hwc_mod->fb_dev); 1924 if (err) 1925 return err; 1926 1927 if (!hwc_mod->fb_dev) { 1928 ALOGE("Framebuffer HAL not opened before HWC"); 1929 return -EFAULT; 1930 } 1931 hwc_mod->fb_dev->bBypassPost = 1; 1932 } 1933 1934 hwc_dev = (omap4_hwc_device_t *)malloc(sizeof(*hwc_dev)); 1935 if (hwc_dev == NULL) 1936 return -ENOMEM; 1937 1938 memset(hwc_dev, 0, sizeof(*hwc_dev)); 1939 1940 hwc_dev->base.common.tag = HARDWARE_DEVICE_TAG; 1941 hwc_dev->base.common.version = HWC_DEVICE_API_VERSION_0_3; 1942 hwc_dev->base.common.module = (hw_module_t *)module; 1943 hwc_dev->base.common.close = omap4_hwc_device_close; 1944 hwc_dev->base.prepare = omap4_hwc_prepare; 1945 hwc_dev->base.set = omap4_hwc_set; 1946 hwc_dev->base.dump = omap4_hwc_dump; 1947 hwc_dev->base.registerProcs = omap4_hwc_registerProcs; 1948 hwc_dev->base.query = omap4_hwc_query; 1949 hwc_dev->base.methods = &omap4_hwc_methods; 1950 hwc_dev->fb_dev = hwc_mod->fb_dev; 1951 *device = &hwc_dev->base.common; 1952 1953 hwc_dev->dsscomp_fd = open("/dev/dsscomp", O_RDWR); 1954 if (hwc_dev->dsscomp_fd < 0) { 1955 ALOGE("failed to open dsscomp (%d)", errno); 1956 err = -errno; 1957 goto done; 1958 } 1959 1960 hwc_dev->hdmi_fb_fd = open("/dev/graphics/fb1", O_RDWR); 1961 if (hwc_dev->hdmi_fb_fd < 0) { 1962 ALOGE("failed to open hdmi fb (%d)", errno); 1963 err = -errno; 1964 goto done; 1965 } 1966 1967 hwc_dev->fb_fd = open("/dev/graphics/fb0", O_RDWR); 1968 if (hwc_dev->fb_fd < 0) { 1969 ALOGE("failed to open fb (%d)", errno); 1970 err = -errno; 1971 goto done; 1972 } 1973 1974 struct fb_fix_screeninfo fix; 1975 if (ioctl(hwc_dev->fb_fd, FBIOGET_FSCREENINFO, &fix)) { 1976 ALOGE("failed to get fb info (%d)", errno); 1977 err = -errno; 1978 goto done; 1979 } 1980 1981 hwc_dev->img_mem_size = fix.smem_len; 1982 hwc_dev->img_mem_ptr = mmap(NULL, fix.smem_len, PROT_WRITE, MAP_SHARED, hwc_dev->fb_fd, 0); 1983 if (hwc_dev->img_mem_ptr == MAP_FAILED) { 1984 ALOGE("failed to map fb memory"); 1985 err = -errno; 1986 goto done; 1987 } 1988 1989 hwc_dev->buffers = malloc(sizeof(buffer_handle_t) * MAX_HW_OVERLAYS); 1990 if (!hwc_dev->buffers) { 1991 err = -ENOMEM; 1992 goto done; 1993 } 1994 1995 int ret = ioctl(hwc_dev->dsscomp_fd, DSSCIOC_QUERY_DISPLAY, &hwc_dev->fb_dis); 1996 if (ret) { 1997 ALOGE("failed to get display info (%d): %m", errno); 1998 err = -errno; 1999 goto done; 2000 } 2001 hwc_dev->ext.lcd_xpy = (float) hwc_dev->fb_dis.width_in_mm / hwc_dev->fb_dis.timings.x_res / 2002 hwc_dev->fb_dis.height_in_mm * hwc_dev->fb_dis.timings.y_res; 2003 2004 if (pipe(hwc_dev->pipe_fds) == -1) { 2005 ALOGE("failed to event pipe (%d): %m", errno); 2006 err = -errno; 2007 goto done; 2008 } 2009 2010 if (pthread_mutex_init(&hwc_dev->lock, NULL)) { 2011 ALOGE("failed to create mutex (%d): %m", errno); 2012 err = -errno; 2013 goto done; 2014 } 2015 if (pthread_create(&hwc_dev->hdmi_thread, NULL, omap4_hwc_hdmi_thread, hwc_dev)) 2016 { 2017 ALOGE("failed to create HDMI listening thread (%d): %m", errno); 2018 err = -errno; 2019 goto done; 2020 } 2021 2022 /* get debug properties */ 2023 2024 /* see if hwc is enabled at all */ 2025 char value[PROPERTY_VALUE_MAX]; 2026 property_get("debug.hwc.rgb_order", value, "1"); 2027 hwc_dev->flags_rgb_order = atoi(value); 2028 property_get("debug.hwc.nv12_only", value, "0"); 2029 hwc_dev->flags_nv12_only = atoi(value); 2030 property_get("debug.hwc.idle", value, "250"); 2031 hwc_dev->idle = atoi(value); 2032 2033 /* get the board specific clone properties */ 2034 /* 0:0:1280:720 */ 2035 if (property_get("persist.hwc.mirroring.region", value, "") <= 0 || 2036 sscanf(value, "%d:%d:%d:%d", 2037 &hwc_dev->ext.mirror_region.left, &hwc_dev->ext.mirror_region.top, 2038 &hwc_dev->ext.mirror_region.right, &hwc_dev->ext.mirror_region.bottom) != 4 || 2039 hwc_dev->ext.mirror_region.left >= hwc_dev->ext.mirror_region.right || 2040 hwc_dev->ext.mirror_region.top >= hwc_dev->ext.mirror_region.bottom) { 2041 struct hwc_rect fb_region = { .right = hwc_dev->fb_dev->base.width, .bottom = hwc_dev->fb_dev->base.height }; 2042 hwc_dev->ext.mirror_region = fb_region; 2043 } 2044 ALOGI("clone region is set to (%d,%d) to (%d,%d)", 2045 hwc_dev->ext.mirror_region.left, hwc_dev->ext.mirror_region.top, 2046 hwc_dev->ext.mirror_region.right, hwc_dev->ext.mirror_region.bottom); 2047 2048 /* read switch state */ 2049 int sw_fd = open("/sys/class/switch/hdmi/state", O_RDONLY); 2050 if (sw_fd >= 0) { 2051 char value; 2052 if (read(sw_fd, &value, 1) == 1) 2053 hwc_dev->ext.hdmi_state = value == '1'; 2054 close(sw_fd); 2055 } 2056 sw_fd = open("/sys/class/switch/dock/state", O_RDONLY); 2057 if (sw_fd >= 0) { 2058 char value; 2059 if (read(sw_fd, &value, 1) == 1) 2060 hwc_dev->ext.force_dock = value == '1'; 2061 close(sw_fd); 2062 } 2063 handle_hotplug(hwc_dev); 2064 2065 ALOGI("omap4_hwc_device_open(rgb_order=%d nv12_only=%d)", 2066 hwc_dev->flags_rgb_order, hwc_dev->flags_nv12_only); 2067 2068 done: 2069 if (err && hwc_dev) { 2070 if (hwc_dev->dsscomp_fd >= 0) 2071 close(hwc_dev->dsscomp_fd); 2072 if (hwc_dev->hdmi_fb_fd >= 0) 2073 close(hwc_dev->hdmi_fb_fd); 2074 if (hwc_dev->fb_fd >= 0) 2075 close(hwc_dev->fb_fd); 2076 pthread_mutex_destroy(&hwc_dev->lock); 2077 free(hwc_dev->buffers); 2078 free(hwc_dev); 2079 } 2080 2081 return err; 2082 } 2083 2084 static struct hw_module_methods_t omap4_hwc_module_methods = { 2085 .open = omap4_hwc_device_open, 2086 }; 2087 2088 omap4_hwc_module_t HAL_MODULE_INFO_SYM = { 2089 .base = { 2090 .common = { 2091 .tag = HARDWARE_MODULE_TAG, 2092 .module_api_version = HWC_MODULE_API_VERSION_0_1, 2093 .hal_api_version = HARDWARE_HAL_API_VERSION, 2094 .id = HWC_HARDWARE_MODULE_ID, 2095 .name = "OMAP 44xx Hardware Composer HAL", 2096 .author = "Texas Instruments", 2097 .methods = &omap4_hwc_module_methods, 2098 }, 2099 }, 2100 }; 2101