summaryrefslogtreecommitdiff
path: root/hwc/hwc.c
diff options
context:
space:
mode:
Diffstat (limited to 'hwc/hwc.c')
-rw-r--r--hwc/hwc.c90
1 files changed, 87 insertions, 3 deletions
diff --git a/hwc/hwc.c b/hwc/hwc.c
index cdbc8e2..174c18b 100644
--- a/hwc/hwc.c
+++ b/hwc/hwc.c
@@ -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) {