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