hwc.c revision 7f2cbf97908a26e0b463d4fa20040b129216f86e
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 <sys/ioctl.h> 23#include <linux/fb.h> 24 25#include <cutils/properties.h> 26#include <cutils/log.h> 27#include <cutils/native_handle.h> 28#include <hardware/hardware.h> 29#include <hardware/hwcomposer.h> 30#include <EGL/egl.h> 31#include <utils/Timers.h> 32#include <hardware_legacy/uevent.h> 33 34#define ASPECT_RATIO_TOLERANCE 0.02f 35 36#ifndef FBIO_WAITFORVSYNC 37#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) 38#endif 39 40#define min(a, b) ( { typeof(a) __a = (a), __b = (b); __a < __b ? __a : __b; } ) 41#define max(a, b) ( { typeof(a) __a = (a), __b = (b); __a > __b ? __a : __b; } ) 42 43#include <video/dsscomp.h> 44 45#include "hal_public.h" 46 47#define MAX_HW_OVERLAYS 4 48#define NUM_NONSCALING_OVERLAYS 1 49#define HAL_PIXEL_FORMAT_BGRX_8888 0x1FF 50#define HAL_PIXEL_FORMAT_TI_NV12 0x100 51#define HAL_PIXEL_FORMAT_TI_NV12_PADDED 0x101 52#define MAX_TILER_SLOT (16 << 20) 53 54#define MIN(a,b) ((a)<(b)?(a):(b)) 55#define MAX(a,b) ((a)>(b)?(a):(b)) 56#define CLAMP(x,low,high) (((x)>(high))?(high):(((x)<(low))?(low):(x))) 57 58enum { 59 EXT_ROTATION = 3, /* rotation while mirroring */ 60 EXT_HFLIP = (1 << 2), /* flip l-r on output (after rotation) */ 61 EXT_TRANSFORM = EXT_ROTATION | EXT_HFLIP, 62 EXT_ON = (1 << 3), /* copy output to other display */ 63 EXT_DOCK = (1 << 4), /* docking only */ 64 EXT_TV = (1 << 5), /* using TV for mirroring */ 65}; 66 67struct omap4_hwc_module { 68 hwc_module_t base; 69 70 IMG_framebuffer_device_public_t *fb_dev; 71}; 72typedef struct omap4_hwc_module omap4_hwc_module_t; 73 74struct omap4_hwc_device { 75 hwc_composer_device_t base; 76 hwc_procs_t *procs; 77 pthread_t hdmi_thread; 78 pthread_mutex_t lock; 79 int dsscomp_fd; 80 int fb_fd; 81 int hdmi_fb_fd; 82 83 __u16 ext_width; 84 __u16 ext_height; 85 __u32 ext_xres; 86 __u32 ext_yres; 87 float m[2][3]; 88 IMG_framebuffer_device_public_t *fb_dev; 89 struct dsscomp_setup_dispc_data dsscomp_data; 90 struct dsscomp_display_info fb_dis; 91 92 buffer_handle_t *buffers; 93 int use_sgx; 94 int swap_rb; 95 int use_tv; 96 int mirror; 97 unsigned int post2_layers; 98 int last_ext_ovls; 99 int last_int_ovls; 100 int ext_ovls; 101 102 int flags_rgb_order; 103 int flags_nv12_only; 104 int ext; 105}; 106typedef struct omap4_hwc_device omap4_hwc_device_t; 107 108static int debug = 0; 109 110static void dump_layer(hwc_layer_t const* l) 111{ 112 LOGD("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}", 113 l->compositionType, l->flags, l->handle, l->transform, l->blending, 114 l->sourceCrop.left, 115 l->sourceCrop.top, 116 l->sourceCrop.right, 117 l->sourceCrop.bottom, 118 l->displayFrame.left, 119 l->displayFrame.top, 120 l->displayFrame.right, 121 l->displayFrame.bottom); 122} 123 124static void dump_dsscomp(struct dsscomp_setup_dispc_data *d) 125{ 126 unsigned i; 127 128 LOGD("[%08x] set: %c%c%c %d ovls\n", 129 d->sync_id, 130 (d->mode & DSSCOMP_SETUP_MODE_APPLY) ? 'A' : '-', 131 (d->mode & DSSCOMP_SETUP_MODE_DISPLAY) ? 'D' : '-', 132 (d->mode & DSSCOMP_SETUP_MODE_CAPTURE) ? 'C' : '-', 133 d->num_ovls); 134 135 for (i = 0; i < d->num_mgrs; i++) { 136 struct dss2_mgr_info *mi = d->mgrs + i; 137 LOGD(" (dis%d alpha=%d col=%08x ilace=%d)\n", 138 mi->ix, 139 mi->alpha_blending, mi->default_color, 140 mi->interlaced); 141 } 142 143 for (i = 0; i < d->num_ovls; i++) { 144 struct dss2_ovl_info *oi = d->ovls + i; 145 struct dss2_ovl_cfg *c = &oi->cfg; 146 if (c->zonly) 147 LOGE("ovl%d(%s z%d)\n", 148 c->ix, c->enabled ? "ON" : "off", c->zorder); 149 else 150 LOGE("ovl%d(%s z%d %x%s *%d%% %d*%d:%d,%d+%d,%d rot%d%s => %d,%d+%d,%d %p/%p|%d)\n", 151 c->ix, c->enabled ? "ON" : "off", c->zorder, c->color_mode, 152 c->pre_mult_alpha ? " premult" : "", 153 (c->global_alpha * 100 + 128) / 255, 154 c->width, c->height, c->crop.x, c->crop.y, 155 c->crop.w, c->crop.h, 156 c->rotation, c->mirror ? "+mir" : "", 157 c->win.x, c->win.y, c->win.w, c->win.h, 158 (void *) oi->ba, (void *) oi->uv, c->stride); 159 } 160} 161 162static int omap4_hwc_is_valid_format(int format) 163{ 164 switch(format) { 165 case HAL_PIXEL_FORMAT_RGB_565: 166 case HAL_PIXEL_FORMAT_RGBX_8888: 167 case HAL_PIXEL_FORMAT_RGBA_8888: 168 case HAL_PIXEL_FORMAT_BGRA_8888: 169 case HAL_PIXEL_FORMAT_BGRX_8888: 170 case HAL_PIXEL_FORMAT_TI_NV12: 171 case HAL_PIXEL_FORMAT_TI_NV12_PADDED: 172 return 1; 173 174 default: 175 LOGI("invalid format %d", format); 176 return 0; 177 } 178} 179 180static int scaled(hwc_layer_t *layer) 181{ 182 int w = layer->sourceCrop.right - layer->sourceCrop.left; 183 int h = layer->sourceCrop.bottom - layer->sourceCrop.top; 184 185 if (layer->transform & HWC_TRANSFORM_ROT_90) { 186 int t = w; 187 w = h; 188 h = t; 189 } 190 191 return (layer->displayFrame.right - layer->displayFrame.left != w || 192 layer->displayFrame.bottom - layer->displayFrame.top != h); 193} 194 195static int sync_id = 0; 196 197#define is_BLENDED(blending) ((blending) != HWC_BLENDING_NONE) 198 199#define is_RGB(format) ((format) == HAL_PIXEL_FORMAT_BGRA_8888 || (format) == HAL_PIXEL_FORMAT_RGB_565 || (format) == HAL_PIXEL_FORMAT_BGRX_8888) 200#define is_BGR(format) ((format) == HAL_PIXEL_FORMAT_RGBX_8888 || (format) == HAL_PIXEL_FORMAT_RGBA_8888) 201#define is_NV12(format) ((format) == HAL_PIXEL_FORMAT_TI_NV12 || (format) == HAL_PIXEL_FORMAT_TI_NV12_PADDED) 202 203static unsigned int mem1d(IMG_native_handle_t *handle) 204{ 205 if (handle == NULL) 206 return 0; 207 208 int bpp = is_NV12(handle->iFormat) ? 0 : (handle->iFormat == HAL_PIXEL_FORMAT_RGB_565 ? 2 : 4); 209 int stride = ALIGN(handle->iWidth, HW_ALIGN) * bpp; 210 return stride * handle->iHeight; 211} 212 213static void 214omap4_hwc_setup_layer_base(struct dss2_ovl_cfg *oc, int index, int format, int width, int height) 215{ 216 unsigned int bits_per_pixel; 217 218 /* YUV2RGB conversion */ 219 const struct omap_dss_cconv_coefs ctbl_bt601_5 = { 220 298, 409, 0, 298, -208, -100, 298, 0, 517, 0, 221 }; 222 223 /* convert color format */ 224 switch (format) { 225 case HAL_PIXEL_FORMAT_RGBX_8888: 226 /* Should be XBGR32, but this isn't supported */ 227 oc->color_mode = OMAP_DSS_COLOR_RGB24U; 228 bits_per_pixel = 32; 229 break; 230 231 case HAL_PIXEL_FORMAT_RGBA_8888: 232 /* Should be ABGR32, but this isn't supported */ 233 oc->color_mode = OMAP_DSS_COLOR_ARGB32; 234 bits_per_pixel = 32; 235 break; 236 237 case HAL_PIXEL_FORMAT_BGRA_8888: 238 oc->color_mode = OMAP_DSS_COLOR_ARGB32; 239 bits_per_pixel = 32; 240 break; 241 242 case HAL_PIXEL_FORMAT_BGRX_8888: 243 oc->color_mode = OMAP_DSS_COLOR_RGB24U; 244 bits_per_pixel = 32; 245 break; 246 247 case HAL_PIXEL_FORMAT_RGB_565: 248 oc->color_mode = OMAP_DSS_COLOR_RGB16; 249 bits_per_pixel = 16; 250 break; 251 252 case HAL_PIXEL_FORMAT_TI_NV12: 253 case HAL_PIXEL_FORMAT_TI_NV12_PADDED: 254 oc->color_mode = OMAP_DSS_COLOR_NV12; 255 bits_per_pixel = 8; 256 oc->cconv = ctbl_bt601_5; 257 break; 258 259 default: 260 /* Should have been filtered out */ 261 LOGV("Unsupported pixel format"); 262 return; 263 } 264 265 oc->width = width; 266 oc->height = height; 267 oc->stride = ALIGN(width, HW_ALIGN) * bits_per_pixel / 8; 268 269 oc->enabled = 1; 270 oc->global_alpha = 255; 271 oc->zorder = index; 272 oc->ix = 0; 273 274 /* defaults for SGX framebuffer renders */ 275 oc->crop.w = oc->win.w = width; 276 oc->crop.h = oc->win.h = height; 277 278 /* for now interlacing and vc1 info is not supplied */ 279 oc->ilace = OMAP_DSS_ILACE_NONE; 280 oc->vc1.enable = 0; 281} 282 283static void 284omap4_hwc_setup_layer(omap4_hwc_device_t *hwc_dev, struct dss2_ovl_info *ovl, 285 hwc_layer_t *layer, int index, 286 int format, int width, int height) 287{ 288 struct dss2_ovl_cfg *oc = &ovl->cfg; 289 290 //dump_layer(layer); 291 292 if (format == HAL_PIXEL_FORMAT_BGRA_8888 && !is_BLENDED(layer->blending)) { 293 format = HAL_PIXEL_FORMAT_BGRX_8888; 294 } 295 296 omap4_hwc_setup_layer_base(oc, index, format, width, height); 297 298 /* convert transformation - assuming 0-set config */ 299 if (layer->transform & HWC_TRANSFORM_FLIP_H) 300 oc->mirror = 1; 301 if (layer->transform & HWC_TRANSFORM_FLIP_V) { 302 oc->rotation = 2; 303 oc->mirror = !oc->mirror; 304 } 305 if (layer->transform & HWC_TRANSFORM_ROT_90) { 306 oc->rotation += oc->mirror ? -1 : 1; 307 oc->rotation &= 3; 308 } 309 310 oc->pre_mult_alpha = layer->blending == HWC_BLENDING_PREMULT; 311 312 /* display position */ 313 oc->win.x = layer->displayFrame.left; 314 oc->win.y = layer->displayFrame.top; 315 oc->win.w = layer->displayFrame.right - layer->displayFrame.left; 316 oc->win.h = layer->displayFrame.bottom - layer->displayFrame.top; 317 318 /* crop */ 319 oc->crop.x = layer->sourceCrop.left; 320 oc->crop.y = layer->sourceCrop.top; 321 oc->crop.w = layer->sourceCrop.right - layer->sourceCrop.left; 322 oc->crop.h = layer->sourceCrop.bottom - layer->sourceCrop.top; 323} 324 325const float m_unit[2][3] = { { 1., 0., 0. }, { 0., 1., 0. } }; 326 327static inline void m_translate(float m[2][3], int dx, int dy) 328{ 329 m[0][2] += dx; 330 m[1][2] += dy; 331} 332 333static inline void m_scale1(float m[3], int from, int to) 334{ 335 m[0] = m[0] * to / from; 336 m[1] = m[1] * to / from; 337 m[2] = m[2] * to / from; 338} 339 340static inline void m_scale(float m[2][3], int x_from, int x_to, int y_from, int y_to) 341{ 342 m_scale1(m[0], x_from, x_to); 343 m_scale1(m[1], y_from, y_to); 344} 345 346static void m_rotate(float m[2][3], int quarter_turns) 347{ 348 if (quarter_turns & 2) 349 m_scale(m, 1, -1, 1, -1); 350 if (quarter_turns & 1) { 351 int q; 352 q = m[0][0]; m[0][0] = -m[1][0]; m[1][0] = q; 353 q = m[0][1]; m[0][1] = -m[1][1]; m[1][1] = q; 354 q = m[0][2]; m[0][2] = -m[1][2]; m[1][2] = q; 355 } 356} 357 358static inline int m_round(float x) 359{ 360 /* int truncates towards 0 */ 361 return (int) (x < 0 ? x - 0.5 : x + 0.5); 362} 363 364/* 365 * assuming xratio:yratio original pixel ratio, calculate the adjusted width 366 * and height for a screen of xres/yres and physical size of width/height. 367 * The adjusted size is the largest that fits into the screen. 368 */ 369static void get_max_dimensions(__u32 orig_xres, __u32 orig_yres, 370 __u32 orig_xratio, __u32 orig_yratio, 371 __u32 scr_xres, __u32 scr_yres, 372 __u32 scr_width, __u32 scr_height, 373 __u32 *adj_xres, __u32 *adj_yres) 374{ 375 /* assume full screen (largest size)*/ 376 *adj_xres = scr_xres; 377 *adj_yres = scr_yres; 378 379 /* assume 1:1 pixel ratios if none supplied */ 380 if (!scr_width || !scr_height) { 381 scr_width = scr_xres; 382 scr_height = scr_yres; 383 } 384 if (!orig_xratio || !orig_yratio) { 385 orig_xratio = 1; 386 orig_yratio = 1; 387 } 388 389 /* trim to keep aspect ratio */ 390 float x_factor = orig_xres * orig_xratio * (float) scr_height; 391 float y_factor = orig_yres * orig_yratio * (float) scr_width; 392 393 /* allow for tolerance so we avoid scaling if framebuffer is standard size */ 394 if (x_factor < y_factor * (1.f - ASPECT_RATIO_TOLERANCE)) 395 *adj_xres = (__u32) (x_factor * *adj_xres / y_factor + 0.5); 396 else if (x_factor * (1.f - ASPECT_RATIO_TOLERANCE) > y_factor) 397 *adj_yres = (__u32) (y_factor * *adj_yres / x_factor + 0.5); 398} 399 400static void set_ext_matrix(omap4_hwc_device_t *hwc_dev, int orig_w, int orig_h) 401{ 402 /* assume 1:1 lcd pixel ratio */ 403 int source_x = 1; 404 int source_y = 1; 405 406 /* reorientation matrix is: 407 m = (center-from-target-center) * (scale-to-target) * (mirror) * (rotate) * (center-to-original-center) */ 408 409 memcpy(hwc_dev->m, m_unit, sizeof(m_unit)); 410 m_translate(hwc_dev->m, -orig_w >> 1, -orig_h >> 1); 411 m_rotate(hwc_dev->m, hwc_dev->ext & 3); 412 if (hwc_dev->ext & EXT_HFLIP) 413 m_scale(hwc_dev->m, 1, -1, 1, 1); 414 415 if (hwc_dev->ext & EXT_ROTATION & 1) { 416 int q = orig_w; 417 orig_w = orig_h; 418 orig_h = q; 419 q = source_x; 420 source_x = source_y; 421 source_y = q; 422 } 423 424 /* get target size */ 425 __u32 adj_xres, adj_yres; 426 get_max_dimensions(orig_w, orig_h, source_x, source_y, 427 hwc_dev->ext_xres, hwc_dev->ext_yres, hwc_dev->ext_width, hwc_dev->ext_height, 428 &adj_xres, &adj_yres); 429 430 m_scale(hwc_dev->m, orig_w, adj_xres, orig_h, adj_yres); 431 m_translate(hwc_dev->m, hwc_dev->ext_xres >> 1, hwc_dev->ext_yres >> 1); 432} 433 434static void 435omap4_hwc_create_ext_matrix(omap4_hwc_device_t *hwc_dev) 436{ 437 /* use VGA external resolution as default */ 438 if (!hwc_dev->ext_xres || 439 !hwc_dev->ext_yres) { 440 hwc_dev->ext_xres = 640; 441 hwc_dev->ext_yres = 480; 442 } 443 444 /* if docking, we cannot create the matrix ahead of time as it depends on input size */ 445 if (hwc_dev->ext && !(hwc_dev->ext & EXT_DOCK)) 446 set_ext_matrix(hwc_dev, hwc_dev->fb_dev->base.width, hwc_dev->fb_dev->base.height); 447} 448 449static void 450omap4_hwc_adjust_ext_layer(omap4_hwc_device_t *hwc_dev, struct dss2_ovl_info *ovl) 451{ 452 struct dss2_ovl_cfg *oc = &ovl->cfg; 453 float x, y, w, h; 454 455 /* display position */ 456 x = hwc_dev->m[0][0] * oc->win.x + hwc_dev->m[0][1] * oc->win.y + hwc_dev->m[0][2]; 457 y = hwc_dev->m[1][0] * oc->win.x + hwc_dev->m[1][1] * oc->win.y + hwc_dev->m[1][2]; 458 w = hwc_dev->m[0][0] * oc->win.w + hwc_dev->m[0][1] * oc->win.h; 459 h = hwc_dev->m[1][0] * oc->win.w + hwc_dev->m[1][1] * oc->win.h; 460 oc->win.x = m_round(w > 0 ? x : x + w); 461 oc->win.y = m_round(h > 0 ? y : y + h); 462 oc->win.w = m_round(w > 0 ? w : -w); 463 oc->win.h = m_round(h > 0 ? h : -h); 464 465 /* combining transformations: F^a*R^b*F^i*R^j = F^(a+b)*R^(j+b*(-1)^i), because F*R = R^(-1)*F */ 466 oc->rotation += (oc->mirror ? -1 : 1) * (hwc_dev->ext & EXT_ROTATION); 467 oc->rotation &= 3; 468 if (hwc_dev->ext & EXT_HFLIP) 469 oc->mirror = !oc->mirror; 470} 471 472static struct dsscomp_dispc_limitations { 473 __u8 max_xdecim_2d; 474 __u8 max_ydecim_2d; 475 __u8 max_xdecim_1d; 476 __u8 max_ydecim_1d; 477 __u32 fclk; 478 __u8 max_downscale; 479 __u8 min_width; 480 __u16 integer_scale_ratio_limit; 481} limits = { 482 .max_xdecim_1d = 16, 483 .max_xdecim_2d = 16, 484 .max_ydecim_1d = 16, 485 .max_ydecim_2d = 2, 486 .fclk = 170666666, 487 .max_downscale = 4, 488 .min_width = 2, 489 .integer_scale_ratio_limit = 2048, 490}; 491 492static int omap4_hwc_can_scale(int src_w, int src_h, int dst_w, int dst_h, int is_nv12, 493 struct dsscomp_display_info *dis, struct dsscomp_dispc_limitations *limits) 494{ 495 __u32 fclk = limits->fclk / 1000; 496 __u32 pclk = dis->timings.pixel_clock; 497 498 /* ERRATAs */ 499 /* cannot render 1-width layers on DSI video mode panels - we just disallow all 1-width LCD layers */ 500 if (dis->channel != OMAP_DSS_CHANNEL_DIGIT && dst_w < limits->min_width) 501 return 0; 502 503 /* NOTE: no support for checking YUV422 layers that are tricky to scale */ 504 505 /* max downscale */ 506 if (dst_h < src_h / limits->max_downscale / (is_nv12 ? limits->max_ydecim_2d : limits->max_ydecim_1d)) 507 return 0; 508 509 /* :HACK: limit horizontal downscale well below theoretical limit as we saw display artifacts */ 510 if (dst_w < src_w / 4) 511 return 0; 512 513 /* max horizontal downscale is 4, or the fclk/pixclk */ 514 if (fclk > pclk * limits->max_downscale) 515 fclk = pclk * limits->max_downscale; 516 /* for small parts, we need to use integer fclk/pixclk */ 517 if (src_w < limits->integer_scale_ratio_limit) 518 fclk = fclk / pclk * pclk; 519 if (dst_w < src_w * pclk / fclk / (is_nv12 ? limits->max_xdecim_2d : limits->max_xdecim_1d)) 520 return 0; 521 522 return 1; 523} 524 525static int omap4_hwc_can_scale_layer(omap4_hwc_device_t *hwc_dev, hwc_layer_t *layer, IMG_native_handle_t *handle) 526{ 527 int src_w = layer->sourceCrop.right - layer->sourceCrop.left; 528 int src_h = layer->sourceCrop.bottom - layer->sourceCrop.top; 529 int dst_w = layer->displayFrame.right - layer->displayFrame.left; 530 int dst_h = layer->displayFrame.bottom - layer->displayFrame.top; 531 532 /* account for 90-degree rotation */ 533 if (layer->transform & HWC_TRANSFORM_ROT_90) { 534 int tmp = src_w; 535 src_w = src_h; 536 src_h = tmp; 537 } 538 539 return omap4_hwc_can_scale(src_w, src_h, dst_w, dst_h, is_NV12(handle->iFormat), &hwc_dev->fb_dis, &limits); 540} 541 542static int omap4_hwc_is_valid_layer(omap4_hwc_device_t *hwc_dev, 543 hwc_layer_t *layer, 544 IMG_native_handle_t *handle) 545{ 546 /* Skip layers are handled by SF */ 547 if ((layer->flags & HWC_SKIP_LAYER) || !handle) 548 return 0; 549 550 if (!omap4_hwc_is_valid_format(handle->iFormat)) 551 return 0; 552 553 /* 1D buffers: no transform, must fit in TILER slot */ 554 if (!is_NV12(handle->iFormat)) { 555 if (layer->transform) 556 return 0; 557 if (mem1d(handle) > MAX_TILER_SLOT) 558 return 0; 559 } 560 561 return omap4_hwc_can_scale_layer(hwc_dev, layer, handle); 562} 563 564struct counts { 565 unsigned int possible_overlay_layers; 566 unsigned int composited_layers; 567 unsigned int scaled_layers; 568 unsigned int RGB; 569 unsigned int BGR; 570 unsigned int NV12; 571 unsigned int displays; 572 unsigned int max_hw_overlays; 573 unsigned int max_scaling_overlays; 574 unsigned int mem; 575}; 576 577static inline int can_dss_render_all(omap4_hwc_device_t *hwc_dev, struct counts *num) 578{ 579 int tv = hwc_dev->ext & EXT_TV; 580 int nonscaling_ovls = NUM_NONSCALING_OVERLAYS; 581 int tform = hwc_dev->ext & EXT_TRANSFORM; 582 num->max_hw_overlays = MAX_HW_OVERLAYS; 583 584 /* 585 * We cannot atomically switch overlays from one display to another. First, they 586 * have to be disabled, and the disabling has to take effect on the current display. 587 * We keep track of the available number of overlays here. 588 */ 589 if (hwc_dev->ext & EXT_DOCK) { 590 /* some overlays may already be used by the external display, so we account for this */ 591 592 /* reserve just a video pipeline for HDMI if docking */ 593 hwc_dev->ext_ovls = num->NV12 ? 1 : 0; 594 num->max_hw_overlays -= max(hwc_dev->ext_ovls, hwc_dev->last_ext_ovls); 595 } else if (hwc_dev->ext) { 596 /* 597 * otherwise, manage just from half the pipelines. NOTE: there is 598 * no danger of having used too many overlays for external display here. 599 */ 600 num->max_hw_overlays >>= 1; 601 nonscaling_ovls >>= 1; 602 hwc_dev->ext_ovls = MAX_HW_OVERLAYS - num->max_hw_overlays; 603 } else { 604 num->max_hw_overlays -= hwc_dev->last_ext_ovls; 605 hwc_dev->ext_ovls = 0; 606 } 607 608 /* 609 * :TRICKY: We may not have enough overlays on the external display. We "reserve" them 610 * here to figure out if mirroring is supported, but may not do mirroring for the first 611 * frame while the overlays required for it are cleared. 612 */ 613 hwc_dev->ext_ovls = min(MAX_HW_OVERLAYS - hwc_dev->last_int_ovls, hwc_dev->ext_ovls); 614 615 /* if not docking, we may be limited by last used external overlays */ 616 if (hwc_dev->ext_ovls && hwc_dev->ext && !(hwc_dev->ext & EXT_DOCK)) 617 num->max_hw_overlays = hwc_dev->ext_ovls; 618 619 num->max_scaling_overlays = num->max_hw_overlays - nonscaling_ovls; 620 621 return /* must have at least one layer if using composition bypass to get sync object */ 622 num->possible_overlay_layers && 623 num->possible_overlay_layers <= num->max_hw_overlays && 624 num->possible_overlay_layers == num->composited_layers && 625 num->scaled_layers <= num->max_scaling_overlays && 626 /* fits into TILER slot */ 627 num->mem <= MAX_TILER_SLOT && 628 /* we cannot clone non-NV12 transformed layers */ 629 (!tform || num->NV12 == num->possible_overlay_layers) && 630 /* HDMI cannot display BGR */ 631 (num->BGR == 0 || (num->RGB == 0 && !tv) || !hwc_dev->flags_rgb_order); 632} 633 634static inline int can_dss_render_layer(omap4_hwc_device_t *hwc_dev, 635 hwc_layer_t *layer) 636{ 637 IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; 638 639 int tv = hwc_dev->ext & EXT_TV; 640 int tform = hwc_dev->ext & EXT_TRANSFORM; 641 642 return omap4_hwc_is_valid_layer(hwc_dev, layer, handle) && 643 /* cannot rotate non-NV12 layers on external display */ 644 (!hwc_dev->ext || (hwc_dev->ext & EXT_DOCK) || !tform || is_NV12(handle->iFormat)) && 645 /* skip non-NV12 layers if also using SGX (if nv12_only flag is set) */ 646 (!hwc_dev->flags_nv12_only || (!hwc_dev->use_sgx || is_NV12(handle->iFormat))) && 647 /* make sure RGB ordering is consistent (if rgb_order flag is set) */ 648 (!(hwc_dev->swap_rb ? is_RGB(handle->iFormat) : is_BGR(handle->iFormat)) || 649 !hwc_dev->flags_rgb_order) && 650 /* TV can only render RGB */ 651 !(tv && is_BGR(handle->iFormat)) && 652 /* we can only rotate TILER2D buffers for external displays */ 653 !(tform && !is_NV12(handle->iFormat)); 654} 655 656static int omap4_hwc_prepare(struct hwc_composer_device *dev, hwc_layer_list_t* list) 657{ 658 omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev; 659 struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->dsscomp_data; 660 struct counts num = { .composited_layers = list ? list->numHwLayers : 0 }; 661 unsigned int i; 662 663 pthread_mutex_lock(&hwc_dev->lock); 664 memset(dsscomp, 0x0, sizeof(*dsscomp)); 665 dsscomp->sync_id = sync_id++; 666 667 /* Figure out how many layers we can support via DSS */ 668 for (i = 0; list && i < list->numHwLayers; i++) { 669 hwc_layer_t *layer = &list->hwLayers[i]; 670 IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; 671 672 layer->compositionType = HWC_FRAMEBUFFER; 673 674 if (omap4_hwc_is_valid_layer(hwc_dev, layer, handle)) { 675 num.possible_overlay_layers++; 676 677 /* NV12 layers can only be rendered on scaling overlays */ 678 if (scaled(layer) || is_NV12(handle->iFormat)) 679 num.scaled_layers++; 680 681 if (is_BGR(handle->iFormat)) 682 num.BGR++; 683 else if (is_RGB(handle->iFormat)) 684 num.RGB++; 685 else if (is_NV12(handle->iFormat)) 686 num.NV12++; 687 688 num.mem += mem1d(handle); 689 } 690 } 691 692 /* phase 3 logic */ 693 if (can_dss_render_all(hwc_dev, &num)) { 694 /* All layers can be handled by the DSS -- don't use SGX for composition */ 695 hwc_dev->use_sgx = 0; 696 hwc_dev->swap_rb = num.BGR != 0; 697 } else { 698 /* Use SGX for composition plus first 3 layers that are DSS renderable */ 699 hwc_dev->use_sgx = 1; 700 hwc_dev->swap_rb = is_BGR(hwc_dev->fb_dev->base.format); 701 } 702 if (debug) { 703 LOGD("prepare (%d) - %s (comp=%d, poss=%d/%d scaled, RGB=%d,BGR=%d,NV12=%d) (ext=%x, %dex/%dmx (last %dex,%din)\n", 704 dsscomp->sync_id, 705 hwc_dev->use_sgx ? "SGX+OVL" : "all-OVL", 706 num.composited_layers, 707 num.possible_overlay_layers, num.scaled_layers, 708 num.RGB, num.BGR, num.NV12, 709 hwc_dev->ext, hwc_dev->ext_ovls, num.max_hw_overlays, hwc_dev->last_ext_ovls, hwc_dev->last_int_ovls); 710 } 711 712 /* setup pipes */ 713 dsscomp->num_ovls = hwc_dev->use_sgx; 714 int z = 0; 715 int fb_z = -1; 716 int scaled_gfx = 0; 717 int ix_nv12 = -1; 718 719 /* set up if DSS layers */ 720 unsigned int mem_used = 0; 721 for (i = 0; list && i < list->numHwLayers; i++) { 722 hwc_layer_t *layer = &list->hwLayers[i]; 723 IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; 724 725 if (dsscomp->num_ovls < num.max_hw_overlays && 726 can_dss_render_layer(hwc_dev, layer) && 727 mem_used + mem1d(handle) < MAX_TILER_SLOT && 728 /* can't have a transparent overlay in the middle of the framebuffer stack */ 729 !(is_BLENDED(layer->blending) && fb_z >= 0)) { 730 /* render via DSS overlay */ 731 mem_used += mem1d(handle); 732 layer->compositionType = HWC_OVERLAY; 733 hwc_dev->buffers[dsscomp->num_ovls] = layer->handle; 734 735 omap4_hwc_setup_layer(hwc_dev, 736 &dsscomp->ovls[dsscomp->num_ovls], 737 &list->hwLayers[i], 738 z, 739 handle->iFormat, 740 handle->iWidth, 741 handle->iHeight); 742 743 dsscomp->ovls[dsscomp->num_ovls].cfg.ix = dsscomp->num_ovls; 744 /* just marking dss layers */ 745 dsscomp->ovls[dsscomp->num_ovls].address = (void *) (dsscomp->num_ovls * 4096 + 0xA0000000); 746 dsscomp->ovls[dsscomp->num_ovls].uv = (__u32) hwc_dev->buffers[dsscomp->num_ovls]; 747 748 /* ensure GFX layer is never scaled */ 749 if (dsscomp->num_ovls == 0) { 750 scaled_gfx = scaled(layer) || is_NV12(handle->iFormat); 751 } else if (scaled_gfx && !scaled(layer) && !is_NV12(handle->iFormat)) { 752 /* swap GFX layer with this one */ 753 dsscomp->ovls[dsscomp->num_ovls].cfg.ix = 0; 754 dsscomp->ovls[0].cfg.ix = dsscomp->num_ovls; 755 scaled_gfx = 0; 756 } 757 758 /* remember first NV12 layer */ 759 if (is_NV12(handle->iFormat) && ix_nv12 < 0) 760 ix_nv12 = dsscomp->num_ovls; 761 762 dsscomp->num_ovls++; 763 z++; 764 } else if (hwc_dev->use_sgx) { 765 if (fb_z < 0) { 766 /* NOTE: we are not handling transparent cutout for now */ 767 fb_z = z; 768 z++; 769 } else { 770 /* move fb z-order up (by lowering dss layers) */ 771 while (fb_z < z - 1) 772 dsscomp->ovls[1 + fb_z++].cfg.zorder--; 773 } 774 } 775 } 776 777 /* clear FB above all opaque layers if rendering via SGX */ 778 if (hwc_dev->use_sgx) { 779 for (i = 0; list && i < list->numHwLayers; i++) { 780 hwc_layer_t *layer = &list->hwLayers[i]; 781 IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; 782 if (layer->compositionType == HWC_FRAMEBUFFER) 783 continue; 784 if ((layer->flags & HWC_SKIP_LAYER) || !layer->handle) 785 continue; 786 if (!is_BLENDED(layer->blending)) 787 layer->hints |= HWC_HINT_CLEAR_FB; 788 } 789 } 790 791 /* if scaling GFX (e.g. only 1 scaled surface) use a VID pipe */ 792 if (scaled_gfx) 793 dsscomp->ovls[0].cfg.ix = 1; 794 795 /* assign a z-layer for fb */ 796 if (hwc_dev->use_sgx && fb_z < 0) { 797 fb_z = z; 798 z++; 799 } 800 801 if (hwc_dev->use_sgx) { 802 hwc_dev->buffers[0] = NULL; 803 omap4_hwc_setup_layer_base(&dsscomp->ovls[0].cfg, fb_z, 804 hwc_dev->fb_dev->base.format, 805 hwc_dev->fb_dev->base.width, 806 hwc_dev->fb_dev->base.height); 807 dsscomp->ovls[0].cfg.pre_mult_alpha = 1; 808 dsscomp->ovls[0].uv = (__u32) hwc_dev->buffers[0]; 809 } 810 811 /* mirror layers */ 812 hwc_dev->post2_layers = dsscomp->num_ovls; 813 if (hwc_dev->ext && hwc_dev->ext_ovls) { 814 int ix_back, ix_front, ix; 815 if (hwc_dev->ext & EXT_DOCK) { 816 /* mirror only NV12 layer */ 817 ix_back = ix_front = ix_nv12; 818 } else { 819 /* mirror all layers */ 820 ix_back = 0; 821 ix_front = dsscomp->num_ovls - 1; 822 } 823 824 for (ix = ix_back; ix >= 0 && ix <= ix_front; ix++) { 825 memcpy(dsscomp->ovls + dsscomp->num_ovls, dsscomp->ovls + ix, sizeof(dsscomp->ovls[ix])); 826 dsscomp->ovls[dsscomp->num_ovls].cfg.zorder += hwc_dev->post2_layers; 827 828 /* reserve overlays at end for other display */ 829 dsscomp->ovls[dsscomp->num_ovls].cfg.ix = MAX_HW_OVERLAYS - 1 - (ix - ix_back); 830 dsscomp->ovls[dsscomp->num_ovls].cfg.mgr_ix = 1; 831 dsscomp->ovls[dsscomp->num_ovls].ba = ix; 832 833 if (hwc_dev->ext & EXT_DOCK) { 834 /* full screen video */ 835 dsscomp->ovls[dsscomp->num_ovls].cfg.win.x = 0; 836 dsscomp->ovls[dsscomp->num_ovls].cfg.win.y = 0; 837 set_ext_matrix(hwc_dev, dsscomp->ovls[dsscomp->num_ovls].cfg.win.w, 838 dsscomp->ovls[dsscomp->num_ovls].cfg.win.h); 839 } 840 omap4_hwc_adjust_ext_layer(hwc_dev, dsscomp->ovls + dsscomp->num_ovls); 841 dsscomp->num_ovls++; 842 z++; 843 } 844 } 845 846 if (z != dsscomp->num_ovls || dsscomp->num_ovls > MAX_HW_OVERLAYS) 847 LOGE("**** used %d z-layers for %d overlays\n", z, dsscomp->num_ovls); 848 849 dsscomp->mode = DSSCOMP_SETUP_DISPLAY; 850 dsscomp->mgrs[0].ix = 0; 851 dsscomp->mgrs[0].alpha_blending = 1; 852 dsscomp->mgrs[0].swap_rb = hwc_dev->swap_rb; 853 dsscomp->num_mgrs = 1; 854 855 if (hwc_dev->ext || hwc_dev->last_ext_ovls) { 856 dsscomp->mgrs[1] = dsscomp->mgrs[0]; 857 dsscomp->mgrs[1].ix = 1; 858 dsscomp->num_mgrs++; 859 hwc_dev->ext_ovls = dsscomp->num_ovls - hwc_dev->post2_layers; 860 } 861 pthread_mutex_unlock(&hwc_dev->lock); 862 return 0; 863} 864 865static int omap4_hwc_set(struct hwc_composer_device *dev, hwc_display_t dpy, 866 hwc_surface_t sur, hwc_layer_list_t* list) 867{ 868 omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev; 869 struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->dsscomp_data; 870 int err = 0; 871 unsigned int i; 872 873 pthread_mutex_lock(&hwc_dev->lock); 874 char big_log[1024]; 875 int e = sizeof(big_log); 876 char *end = big_log + e; 877 e -= snprintf(end - e, e, "set H{"); 878 for (i = 0; list && i < list->numHwLayers; i++) { 879 if (i) 880 e -= snprintf(end - e, e, " "); 881 hwc_layer_t *layer = &list->hwLayers[i]; 882 IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; 883 e -= snprintf(end - e, e, "%p:%s,", handle, layer->compositionType == HWC_OVERLAY ? "DSS" : "SGX"); 884 if ((layer->flags & HWC_SKIP_LAYER) || !handle) { 885 e -= snprintf(end - e, e, "SKIP"); 886 continue; 887 } 888 if (layer->flags & HWC_HINT_CLEAR_FB) 889 e -= snprintf(end - e, e, "CLR,"); 890#define FMT(f) ((f) == HAL_PIXEL_FORMAT_TI_NV12 ? "NV12" : \ 891 (f) == HAL_PIXEL_FORMAT_BGRX_8888 ? "xRGB32" : \ 892 (f) == HAL_PIXEL_FORMAT_RGBX_8888 ? "xBGR32" : \ 893 (f) == HAL_PIXEL_FORMAT_BGRA_8888 ? "ARGB32" : \ 894 (f) == HAL_PIXEL_FORMAT_RGBA_8888 ? "ABGR32" : \ 895 (f) == HAL_PIXEL_FORMAT_RGB_565 ? "RGB565" : "??") 896 e -= snprintf(end - e, e, "%d*%d(%s)", handle->iWidth, handle->iHeight, FMT(handle->iFormat)); 897 if (layer->transform) 898 e -= snprintf(end - e, e, "~%d", layer->transform); 899#undef FMT 900 } 901 e -= snprintf(end - e, e, "} D{"); 902 for (i = 0; i < dsscomp->num_ovls; i++) { 903 if (i) 904 e -= snprintf(end - e, e, " "); 905 e -= snprintf(end - e, e, "%d=", dsscomp->ovls[i].cfg.ix); 906#define FMT(f) ((f) == OMAP_DSS_COLOR_NV12 ? "NV12" : \ 907 (f) == OMAP_DSS_COLOR_RGB24U ? "xRGB32" : \ 908 (f) == OMAP_DSS_COLOR_ARGB32 ? "ARGB32" : \ 909 (f) == OMAP_DSS_COLOR_RGB16 ? "RGB565" : "??") 910 if (dsscomp->ovls[i].cfg.enabled) 911 e -= snprintf(end - e, e, "%08x:%d*%d,%s", 912 dsscomp->ovls[i].ba, 913 dsscomp->ovls[i].cfg.width, 914 dsscomp->ovls[i].cfg.height, 915 FMT(dsscomp->ovls[i].cfg.color_mode)); 916#undef FMT 917 else 918 e -= snprintf(end - e, e, "-"); 919 } 920 e -= snprintf(end - e, e, "} L{"); 921 for (i = 0; i < hwc_dev->post2_layers; i++) { 922 if (i) 923 e -= snprintf(end - e, e, " "); 924 e -= snprintf(end - e, e, "%p", hwc_dev->buffers[i]); 925 } 926 e -= snprintf(end - e, e, "}%s\n", hwc_dev->use_sgx ? " swap" : ""); 927 if (debug) { 928 LOGD("%s", big_log); 929 } 930 931 // LOGD("set %d layers (sgx=%d)\n", dsscomp->num_ovls, hwc_dev->use_sgx); 932 933 if (dpy && sur) { 934 // list can be NULL which means hwc is temporarily disabled. 935 // however, if dpy and sur are null it means we're turning the 936 // screen off. no shall not call eglSwapBuffers() in that case. 937 938 if (hwc_dev->use_sgx) { 939 if (!eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur)) { 940 LOGE("eglSwapBuffers error"); 941 err = HWC_EGL_ERROR; 942 goto err_out; 943 } 944 } 945 946 //dump_dsscomp(dsscomp); 947 948 err = hwc_dev->fb_dev->Post2((framebuffer_device_t *)hwc_dev->fb_dev, 949 hwc_dev->buffers, 950 hwc_dev->post2_layers, 951 dsscomp, sizeof(*dsscomp)); 952 953 if (!hwc_dev->use_sgx) { 954 __u32 crt = 0; 955 int err2 = ioctl(hwc_dev->fb_fd, FBIO_WAITFORVSYNC, &crt); 956 if (err2) { 957 LOGE("failed to wait for vsync (%d)", errno); 958 err = err ? : -errno; 959 } 960 } 961 } 962 hwc_dev->last_ext_ovls = hwc_dev->ext_ovls; 963 hwc_dev->last_int_ovls = hwc_dev->post2_layers; 964 if (err) 965 LOGE("Post2 error"); 966 967err_out: 968 pthread_mutex_unlock(&hwc_dev->lock); 969 return err; 970} 971 972static int dump_printf(char *buff, int buff_len, int len, const char *fmt, ...) 973{ 974 va_list ap; 975 976 int print_len; 977 978 va_start(ap, fmt); 979 980 print_len = vsnprintf(buff + len, buff_len - len, fmt, ap); 981 982 va_end(ap); 983 984 return len + print_len; 985} 986 987static void omap4_hwc_dump(struct hwc_composer_device *dev, char *buff, int buff_len) 988{ 989 omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev; 990 struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->dsscomp_data; 991 int len = 0; 992 int i; 993 994 len = dump_printf(buff, buff_len, len, "omap4_hwc %d:\n", dsscomp->num_ovls); 995 996 for (i = 0; i < dsscomp->num_ovls; i++) { 997 struct dss2_ovl_cfg *cfg = &dsscomp->ovls[i].cfg; 998 999 len = dump_printf(buff, buff_len, len, " layer %d:\n", i); 1000 len = dump_printf(buff, buff_len, len, " enabled: %s\n", 1001 cfg->enabled ? "true" : "false"); 1002 len = dump_printf(buff, buff_len, len, " buff: %dx%d stride: %d:\n", 1003 cfg->width, cfg->height, cfg->stride); 1004 len = dump_printf(buff, buff_len, len, " src: (%d,%d) %dx%d\n", 1005 cfg->crop.x, cfg->crop.y, cfg->crop.w, cfg->crop.h); 1006 len = dump_printf(buff, buff_len, len, " dst: (%d,%d) %dx%d\n", 1007 cfg->win.x, cfg->win.y, cfg->win.w, cfg->win.h); 1008 len = dump_printf(buff, buff_len, len, " ix: %d\n", cfg->ix); 1009 len = dump_printf(buff, buff_len, len, " zorder: %d\n\n", cfg->zorder); 1010 } 1011} 1012 1013 1014static int omap4_hwc_device_close(hw_device_t* device) 1015{ 1016 omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) device;; 1017 1018 if (hwc_dev) { 1019 if (hwc_dev->dsscomp_fd >= 0) 1020 close(hwc_dev->dsscomp_fd); 1021 if (hwc_dev->hdmi_fb_fd >= 0) 1022 close(hwc_dev->hdmi_fb_fd); 1023 if (hwc_dev->fb_fd >= 0) 1024 close(hwc_dev->fb_fd); 1025 /* pthread will get killed when parent process exits */ 1026 pthread_mutex_destroy(&hwc_dev->lock); 1027 free(hwc_dev); 1028 } 1029 1030 return 0; 1031} 1032 1033static int omap4_hwc_open_fb_hal(IMG_framebuffer_device_public_t **fb_dev) 1034{ 1035 IMG_gralloc_module_public_t *psGrallocModule; 1036 int err; 1037 1038 err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, 1039 (const hw_module_t**)&psGrallocModule); 1040 if(err) 1041 goto err_out; 1042 1043 if(strcmp(psGrallocModule->base.common.author, 1044 "Imagination Technologies")) 1045 { 1046 err = -EINVAL; 1047 goto err_out; 1048 } 1049 1050 *fb_dev = psGrallocModule->psFrameBufferDevice; 1051 1052 return 0; 1053 1054err_out: 1055 LOGE("Composer HAL failed to load compatible Graphics HAL"); 1056 return err; 1057} 1058 1059static void handle_hotplug(omap4_hwc_device_t *hwc_dev, int state) 1060{ 1061 pthread_mutex_lock(&hwc_dev->lock); 1062 hwc_dev->ext = 0; 1063 if (state) { 1064 struct _qdis { 1065 struct dsscomp_display_info dis; 1066 struct dsscomp_videomode modedb[16]; 1067 } d = { .dis = { .ix = 1 } }; 1068 d.dis.modedb_len = sizeof(d.modedb) / sizeof(*d.modedb); 1069 int ret = ioctl(hwc_dev->dsscomp_fd, DSSCOMP_QUERY_DISPLAY, &d); 1070 if (!ret) { 1071 __u32 i, best = ~0, best_score = 0; 1072 hwc_dev->ext = EXT_ON | 3; 1073 hwc_dev->ext_width = d.dis.width_in_mm; 1074 hwc_dev->ext_height = d.dis.height_in_mm; 1075 hwc_dev->ext_xres = d.dis.timings.x_res; 1076 hwc_dev->ext_yres = d.dis.timings.y_res; 1077 for (i = 0; i < d.dis.modedb_len; i++) { 1078 __u32 score = 0; 1079 __u32 fb_xres = (hwc_dev->ext & 1) ? hwc_dev->fb_dev->base.height : hwc_dev->fb_dev->base.width; 1080 __u32 fb_yres = (hwc_dev->ext & 1) ? hwc_dev->fb_dev->base.width : hwc_dev->fb_dev->base.height; 1081 __u32 fb_area = fb_xres * fb_yres; 1082 __u32 mode_area = d.modedb[i].xres * d.modedb[i].yres; 1083 __u32 ext_width = d.dis.width_in_mm; 1084 __u32 ext_height = d.dis.height_in_mm; 1085 __u32 ext_fb_xres, ext_fb_yres; 1086 1087 if (d.modedb[i].flag & FB_FLAG_RATIO_4_3) { 1088 ext_width = 4; 1089 ext_height = 3; 1090 } else if (d.modedb[i].flag & FB_FLAG_RATIO_16_9) { 1091 ext_width = 16; 1092 ext_height = 9; 1093 } 1094 1095 get_max_dimensions(fb_xres, fb_yres, 1, 1, d.modedb[i].xres, d.modedb[i].yres, 1096 ext_width, ext_height, &ext_fb_xres, &ext_fb_yres); 1097 1098 if (!omap4_hwc_can_scale(fb_xres, fb_yres, ext_fb_xres, ext_fb_yres, 1099 hwc_dev->ext & EXT_TRANSFORM, &d.dis, &limits)) 1100 continue; 1101 1102 /* prefer CEA modes */ 1103 if (d.modedb[i].flag & (FB_FLAG_RATIO_4_3 | FB_FLAG_RATIO_16_9)) 1104 score |= (1 << 30); 1105 1106 /* prefer to upscale (1% tolerance) */ 1107 if (ext_fb_xres >= fb_xres * 99 / 100 && ext_fb_yres >= fb_yres * 99 / 100) 1108 score |= (1 << 29); 1109 1110 /* pick smallest leftover area */ 1111 score |= (1 << 24) * ((16 * ext_fb_xres * ext_fb_yres + (mode_area >> 1)) / mode_area); 1112 1113 /* pick closest screen size */ 1114 if (ext_fb_xres * ext_fb_yres > fb_area) 1115 score |= (1 << 19) * (16 * fb_area / ext_fb_xres / ext_fb_yres); 1116 else 1117 score |= (1 << 19) * (16 * ext_fb_xres * ext_fb_yres / fb_area); 1118 1119 /* pick highest frame rate */ 1120 score |= (1 << 11) * d.modedb[i].refresh; 1121 1122 LOGD("#%d: %dx%d %dHz", i, d.modedb[i].xres, d.modedb[i].yres, d.modedb[i].refresh); 1123 if (debug) 1124 LOGD(" score=%u adj.res=%dx%d", score, ext_fb_xres, ext_fb_yres); 1125 if (best_score < score) { 1126 hwc_dev->ext_width = ext_width; 1127 hwc_dev->ext_height = ext_height; 1128 hwc_dev->ext_xres = d.modedb[i].xres; 1129 hwc_dev->ext_yres = d.modedb[i].yres; 1130 best = i; 1131 best_score = score; 1132 } 1133 } 1134 if (~best) { 1135 struct dsscomp_setup_display_data sdis = { .ix = 1, }; 1136 sdis.mode = d.dis.modedb[best]; 1137 LOGD("picking #%d", best); 1138 ioctl(hwc_dev->dsscomp_fd, DSSCOMP_SETUP_DISPLAY, &sdis); 1139 } else { 1140 __u32 fb_xres = (hwc_dev->ext & 1) ? hwc_dev->fb_dev->base.height : hwc_dev->fb_dev->base.width; 1141 __u32 fb_yres = (hwc_dev->ext & 1) ? hwc_dev->fb_dev->base.width : hwc_dev->fb_dev->base.height; 1142 __u32 ext_width = d.dis.width_in_mm; 1143 __u32 ext_height = d.dis.height_in_mm; 1144 __u32 ext_fb_xres, ext_fb_yres; 1145 1146 get_max_dimensions(fb_xres, fb_yres, 1, 1, d.dis.timings.x_res, d.dis.timings.y_res, 1147 ext_width, ext_height, &ext_fb_xres, &ext_fb_yres); 1148 if (!omap4_hwc_can_scale(fb_xres, fb_yres, ext_fb_xres, ext_fb_yres, 1149 hwc_dev->ext & EXT_TRANSFORM, &d.dis, &limits)) { 1150 LOGE("DSS scaler cannot support HDMI cloning"); 1151 hwc_dev->ext = 0; 1152 } 1153 } 1154 1155 if (hwc_dev->ext) { 1156 if (d.dis.channel == OMAP_DSS_CHANNEL_DIGIT) 1157 hwc_dev->ext |= EXT_TV; 1158 ioctl(hwc_dev->hdmi_fb_fd, FBIOBLANK, FB_BLANK_UNBLANK); 1159 } 1160 } 1161 1162 /* FIXME set up hwc_dev->ext based on mirroring needs */ 1163 char value[PROPERTY_VALUE_MAX]; 1164 property_get("debug.hwc.ext", value, "0"); 1165 hwc_dev->ext |= atoi(value) & EXT_DOCK; 1166 } 1167 omap4_hwc_create_ext_matrix(hwc_dev); 1168 LOGI("external display changed (state=%d, on=%d, dock=%d, tv=%d, trform=%ddeg%s)", state, 1169 !!hwc_dev->ext, !!(hwc_dev->ext & EXT_DOCK), 1170 !!(hwc_dev->ext & EXT_TV), hwc_dev->ext & EXT_ROTATION, 1171 (hwc_dev->ext & EXT_HFLIP) ? "+hflip" : ""); 1172 pthread_mutex_unlock(&hwc_dev->lock); 1173 1174 if (hwc_dev->procs && hwc_dev->procs->invalidate) { 1175 hwc_dev->procs->invalidate(hwc_dev->procs); 1176 usleep(30000); 1177 hwc_dev->procs->invalidate(hwc_dev->procs); 1178 } 1179} 1180 1181static void handle_uevents(omap4_hwc_device_t *hwc_dev, const char *s) 1182{ 1183 if (strcmp(s, "change@/devices/virtual/switch/hdmi")) 1184 return; 1185 1186 s += strlen(s) + 1; 1187 1188 while(*s) { 1189 if (!strncmp(s, "SWITCH_STATE=", strlen("SWITCH_STATE="))) { 1190 int state = atoi(s + strlen("SWITCH_STATE=")); 1191 handle_hotplug(hwc_dev, state); 1192 } 1193 1194 s += strlen(s) + 1; 1195 } 1196} 1197 1198static void *omap4_hwc_hdmi_thread(void *data) 1199{ 1200 omap4_hwc_device_t *hwc_dev = data; 1201 static char uevent_desc[4096]; 1202 uevent_init(); 1203 1204 memset(uevent_desc, 0, sizeof(uevent_desc)); 1205 1206 do { 1207 /* keep last 2 zeroes to ensure double 0 termination */ 1208 uevent_next_event(uevent_desc, sizeof(uevent_desc) - 2); 1209 handle_uevents(hwc_dev, uevent_desc); 1210 } while (1); 1211 1212 return NULL; 1213} 1214 1215static void omap4_hwc_registerProcs(struct hwc_composer_device* dev, 1216 hwc_procs_t const* procs) 1217{ 1218 omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) dev; 1219 1220 hwc_dev->procs = (typeof(hwc_dev->procs)) procs; 1221} 1222 1223static int omap4_hwc_device_open(const hw_module_t* module, const char* name, 1224 hw_device_t** device) 1225{ 1226 omap4_hwc_module_t *hwc_mod = (omap4_hwc_module_t *)module; 1227 omap4_hwc_device_t *hwc_dev; 1228 int err = 0; 1229 1230 if (strcmp(name, HWC_HARDWARE_COMPOSER)) { 1231 return -EINVAL; 1232 } 1233 1234 if (!hwc_mod->fb_dev) { 1235 err = omap4_hwc_open_fb_hal(&hwc_mod->fb_dev); 1236 if (err) 1237 return err; 1238 1239 if (!hwc_mod->fb_dev) { 1240 LOGE("Framebuffer HAL not opened before HWC"); 1241 return -EFAULT; 1242 } 1243 hwc_mod->fb_dev->bBypassPost = 1; 1244 } 1245 1246 hwc_dev = (omap4_hwc_device_t *)malloc(sizeof(*hwc_dev)); 1247 if (hwc_dev == NULL) 1248 return -ENOMEM; 1249 1250 memset(hwc_dev, 0, sizeof(*hwc_dev)); 1251 1252 hwc_dev->base.common.tag = HARDWARE_DEVICE_TAG; 1253 hwc_dev->base.common.version = HWC_API_VERSION; 1254 hwc_dev->base.common.module = (hw_module_t *)module; 1255 hwc_dev->base.common.close = omap4_hwc_device_close; 1256 hwc_dev->base.prepare = omap4_hwc_prepare; 1257 hwc_dev->base.set = omap4_hwc_set; 1258 hwc_dev->base.dump = omap4_hwc_dump; 1259 hwc_dev->base.registerProcs = omap4_hwc_registerProcs; 1260 hwc_dev->fb_dev = hwc_mod->fb_dev; 1261 *device = &hwc_dev->base.common; 1262 1263 hwc_dev->dsscomp_fd = open("/dev/dsscomp", O_RDWR); 1264 if (hwc_dev->dsscomp_fd < 0) { 1265 LOGE("failed to open dsscomp (%d)", errno); 1266 err = -errno; 1267 goto done; 1268 } 1269 1270 hwc_dev->hdmi_fb_fd = open("/dev/graphics/fb1", O_RDWR); 1271 if (hwc_dev->hdmi_fb_fd < 0) { 1272 LOGE("failed to open hdmi fb (%d)", errno); 1273 err = -errno; 1274 goto done; 1275 } 1276 1277 hwc_dev->fb_fd = open("/dev/graphics/fb0", O_RDWR); 1278 if (hwc_dev->fb_fd < 0) { 1279 LOGE("failed to open fb (%d)", errno); 1280 err = -errno; 1281 goto done; 1282 } 1283 1284 hwc_dev->buffers = malloc(sizeof(buffer_handle_t) * MAX_HW_OVERLAYS); 1285 if (!hwc_dev->buffers) { 1286 err = -ENOMEM; 1287 goto done; 1288 } 1289 1290 int ret = ioctl(hwc_dev->dsscomp_fd, DSSCOMP_QUERY_DISPLAY, &hwc_dev->fb_dis); 1291 if (ret) { 1292 LOGE("failed to get display info (%d): %m", errno); 1293 err = -errno; 1294 goto done; 1295 } 1296 1297 if (pthread_mutex_init(&hwc_dev->lock, NULL)) { 1298 LOGE("failed to create mutex (%d): %m", errno); 1299 err = -errno; 1300 goto done; 1301 } 1302 if (pthread_create(&hwc_dev->hdmi_thread, NULL, omap4_hwc_hdmi_thread, hwc_dev)) 1303 { 1304 LOGE("failed to create HDMI listening thread (%d): %m", errno); 1305 err = -errno; 1306 goto done; 1307 } 1308 1309 /* get debug properties */ 1310 1311 /* see if hwc is enabled at all */ 1312 char value[PROPERTY_VALUE_MAX]; 1313 property_get("debug.hwc.rgb_order", value, "1"); 1314 hwc_dev->flags_rgb_order = atoi(value); 1315 property_get("debug.hwc.nv12_only", value, "0"); 1316 hwc_dev->flags_nv12_only = atoi(value); 1317 1318 /* read switch state */ 1319 int sw_fd = open("/sys/class/switch/hdmi/state", O_RDONLY); 1320 int hpd = 0; 1321 if (sw_fd >= 0) { 1322 char value; 1323 if (read(sw_fd, &value, 1) == 1) 1324 hpd = value == '1'; 1325 close(sw_fd); 1326 } 1327 handle_hotplug(hwc_dev, hpd); 1328 1329 LOGE("omap4_hwc_device_open(rgb_order=%d nv12_only=%d)", 1330 hwc_dev->flags_rgb_order, hwc_dev->flags_nv12_only); 1331 1332done: 1333 if (err && hwc_dev) { 1334 if (hwc_dev->dsscomp_fd >= 0) 1335 close(hwc_dev->dsscomp_fd); 1336 if (hwc_dev->hdmi_fb_fd >= 0) 1337 close(hwc_dev->hdmi_fb_fd); 1338 if (hwc_dev->fb_fd >= 0) 1339 close(hwc_dev->fb_fd); 1340 pthread_mutex_destroy(&hwc_dev->lock); 1341 free(hwc_dev->buffers); 1342 free(hwc_dev); 1343 } 1344 1345 return err; 1346} 1347 1348static struct hw_module_methods_t omap4_hwc_module_methods = { 1349 .open = omap4_hwc_device_open, 1350}; 1351 1352omap4_hwc_module_t HAL_MODULE_INFO_SYM = { 1353 .base = { 1354 .common = { 1355 .tag = HARDWARE_MODULE_TAG, 1356 .version_major = 1, 1357 .version_minor = 0, 1358 .id = HWC_HARDWARE_MODULE_ID, 1359 .name = "OMAP 44xx Hardware Composer HAL", 1360 .author = "Texas Instruments", 1361 .methods = &omap4_hwc_module_methods, 1362 }, 1363 }, 1364}; 1365