diff options
Diffstat (limited to 'hwc/hwc.c')
-rw-r--r-- | hwc/hwc.c | 90 |
1 files changed, 87 insertions, 3 deletions
@@ -60,9 +60,13 @@ #include "hal_public.h" #include "rgz_2d.h" +#include <linux/ion.h> +#include <linux/omap_ion.h> +#include <ion/ion.h> + #define MAX_HW_OVERLAYS 4 #define NUM_NONSCALING_OVERLAYS 1 -#define MAX_TILER_SLOT (32 << 20) +#define NUM_EXT_DISPLAY_BACK_BUFFERS 2 struct ext_transform_t { __u8 rotation : 3; /* 90-degree clockwise rotations */ @@ -199,6 +203,8 @@ struct omap4_hwc_device { struct omap_hwc_data comp_data; /* This is a kernel data structure */ struct rgz_blt_entry blit_ops[RGZ_MAX_BLITS]; struct counts stats; + int ion_fd; + struct ion_handle *ion_handles[2]; /* fake vsync event state */ pthread_mutex_t vsync_lock; @@ -1336,8 +1342,21 @@ static int clone_layer(omap4_hwc_device_t *hwc_dev, int ix) { /* reserve overlays at end for other display */ o->cfg.ix = MAX_HW_OVERLAYS - 1 - ext_ovl_ix; o->cfg.mgr_ix = 1; - o->addressing = OMAP_DSS_BUFADDR_OVL_IX; - o->ba = ix; + /* + * Here the assumption is that overlay0 is the one attached to FB. + * Hence this clone_layer call is for FB cloning (provided use_sgx is true). + */ + /* For the external displays whose transform is the same as + * that of primary display, ion_handles would be NULL hence + * the below logic doesn't execute. + */ + if (ix == 0 && hwc_dev->ion_handles[sync_id%2] && hwc_dev->use_sgx) { + o->addressing = OMAP_DSS_BUFADDR_ION; + o->ba = (int)hwc_dev->ion_handles[sync_id%2]; + } else { + o->addressing = OMAP_DSS_BUFADDR_OVL_IX; + o->ba = ix; + } /* use distinct z values (to simplify z-order checking) */ o->cfg.zorder += hwc_dev->post2_layers; @@ -1567,6 +1586,47 @@ void debug_post2(omap4_hwc_device_t *hwc_dev, int nbufs) } } +static int free_tiler2d_buffers(omap4_hwc_device_t *hwc_dev) +{ + int i; + + for (i = 0 ; i < NUM_EXT_DISPLAY_BACK_BUFFERS; i++) { + ion_free(hwc_dev->ion_fd, hwc_dev->ion_handles[i]); + hwc_dev->ion_handles[i] = NULL; + } + return 0; +} + +static int allocate_tiler2d_buffers(omap4_hwc_device_t *hwc_dev) +{ + int ret, i; + size_t stride; + + if (hwc_dev->ion_fd < 0) { + ALOGE("No ion fd, hence can't allocate tiler2d buffers"); + return -1; + } + + for (i = 0; i < NUM_EXT_DISPLAY_BACK_BUFFERS; i++) { + if (hwc_dev->ion_handles[i]) + return 0; + } + + for (i = 0 ; i < NUM_EXT_DISPLAY_BACK_BUFFERS; i++) { + ret = ion_alloc_tiler(hwc_dev->ion_fd, hwc_dev->fb_dev->base.width, hwc_dev->fb_dev->base.height, + TILER_PIXEL_FMT_32BIT, 0, &hwc_dev->ion_handles[i], &stride); + if (ret) + goto handle_error; + + ALOGI("ion handle[%d][%p]", i, hwc_dev->ion_handles[i]); + } + return 0; + +handle_error: + free_tiler2d_buffers(hwc_dev); + return -1; +} + static int omap4_hwc_prepare(struct hwc_composer_device_1 *dev, size_t numDisplays, hwc_display_contents_1_t** displays) { @@ -2151,6 +2211,9 @@ static int omap4_hwc_device_close(hw_device_t* device) close(hwc_dev->hdmi_fb_fd); if (hwc_dev->fb_fd >= 0) close(hwc_dev->fb_fd); + if (hwc_dev->ion_fd >= 0) + ion_close(hwc_dev->ion_fd); + /* pthread will get killed when parent process exits */ pthread_mutex_destroy(&hwc_dev->lock); pthread_mutex_destroy(&hwc_dev->vsync_lock); @@ -2291,8 +2354,19 @@ static void handle_hotplug(omap4_hwc_device_t *hwc_dev) } else ext->mirror.enabled = 0; } + /* Allocate backup buffers for FB rotation + * This is required only if the FB tranform is different from that + * of the external display and the FB is not in TILER2D space + */ + if (ext->mirror.rotation && (limits.fbmem_type != DSSCOMP_FBMEM_TILER2D)) + allocate_tiler2d_buffers(hwc_dev); + } else { ext->last_mode = 0; + if (ext->mirror.rotation && (limits.fbmem_type != DSSCOMP_FBMEM_TILER2D)) { + /* free tiler 2D buffer on detach */ + free_tiler2d_buffers(hwc_dev); + } } ALOGI("external display changed (state=%d, mirror={%s tform=%ddeg%s}, dock={%s tform=%ddeg%s%s}, tv=%d", state, ext->mirror.enabled ? "enabled" : "disabled", @@ -2676,6 +2750,16 @@ static int omap4_hwc_device_open(const hw_module_t* module, const char* name, goto done; } + hwc_dev->ion_fd = ion_open(); + if (hwc_dev->ion_fd < 0) { + ALOGE("failed to open ion driver (%d)", errno); + } + + int i; + for (i = 0; i < NUM_EXT_DISPLAY_BACK_BUFFERS; i++) { + hwc_dev->ion_handles[i] = NULL; + } + /* use default value in case some of requested display parameters missing */ hwc_dev->ext.lcd_xpy = 1.0; if (hwc_dev->fb_dis.timings.x_res && hwc_dev->fb_dis.height_in_mm) { |