summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hwc/hwc.c113
1 files changed, 91 insertions, 22 deletions
diff --git a/hwc/hwc.c b/hwc/hwc.c
index 2762af7..351ba7b 100644
--- a/hwc/hwc.c
+++ b/hwc/hwc.c
@@ -22,7 +22,9 @@
#include <poll.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
+#include <linux/omapfb.h>
#include <sys/mman.h>
+#include <sys/resource.h>
#include <cutils/properties.h>
#include <cutils/log.h>
@@ -30,15 +32,12 @@
#include <hardware/hardware.h>
#include <hardware/hwcomposer.h>
#include <EGL/egl.h>
-#include <utils/Timers.h>
#include <hardware_legacy/uevent.h>
#include <png.h>
-#define ASPECT_RATIO_TOLERANCE 0.02f
+#include <system/graphics.h>
-#ifndef FBIO_WAITFORVSYNC
-#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
-#endif
+#define ASPECT_RATIO_TOLERANCE 0.02f
#define min(a, b) ( { typeof(a) __a = (a), __b = (b); __a < __b ? __a : __b; } )
#define max(a, b) ( { typeof(a) __a = (a), __b = (b); __a > __b ? __a : __b; } )
@@ -1733,26 +1732,45 @@ static void handle_hotplug(omap4_hwc_device_t *hwc_dev)
hwc_dev->procs->invalidate(hwc_dev->procs);
}
-static void handle_uevents(omap4_hwc_device_t *hwc_dev, const char *s)
+static void handle_uevents(omap4_hwc_device_t *hwc_dev, const char *buff, int len)
{
- int dock = !strcmp(s, "change@/devices/virtual/switch/dock");
- if (!dock &&
- strcmp(s, "change@/devices/virtual/switch/hdmi"))
- return;
+ int dock;
+ int hdmi;
+ int vsync;
+ int state = 0;
+ uint64_t timestamp = 0;
+ const char *s = buff;
+
+ dock = !strcmp(s, "change@/devices/virtual/switch/dock");
+ hdmi = !strcmp(s, "change@/devices/virtual/switch/hdmi");
+ vsync = !strcmp(s, "change@/devices/virtual/switch/omapfb-vsync");
+
+ if (!dock && !vsync && !hdmi)
+ return;
s += strlen(s) + 1;
while(*s) {
- if (!strncmp(s, "SWITCH_STATE=", strlen("SWITCH_STATE="))) {
- int state = atoi(s + strlen("SWITCH_STATE="));
- if (dock)
- hwc_dev->ext.force_dock = state == 1;
- else
- hwc_dev->ext.hdmi_state = state == 1;
- handle_hotplug(hwc_dev);
- }
+ if (!strncmp(s, "SWITCH_STATE=", strlen("SWITCH_STATE=")))
+ state = atoi(s + strlen("SWITCH_STATE="));
+ else if (!strncmp(s, "SWITCH_TIME=", strlen("SWITCH_TIME=")))
+ timestamp = strtoull(s + strlen("SWITCH_TIME="), NULL, 0);
s += strlen(s) + 1;
+ if (s - buff >= len)
+ break;
+ }
+
+ if (vsync) {
+ if (hwc_dev->procs && hwc_dev->procs->vsync) {
+ hwc_dev->procs->vsync(hwc_dev->procs, 0, timestamp);
+ }
+ } else {
+ if (dock)
+ hwc_dev->ext.force_dock = state == 1;
+ else
+ hwc_dev->ext.hdmi_state = state == 1;
+ handle_hotplug(hwc_dev);
}
}
@@ -1765,6 +1783,8 @@ static void *omap4_hwc_hdmi_thread(void *data)
int timeout;
int err;
+ setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
+
uevent_init();
fds[0].fd = uevent_get_fd();
@@ -1814,8 +1834,8 @@ static void *omap4_hwc_hdmi_thread(void *data)
if (fds[0].revents & POLLIN) {
/* keep last 2 zeroes to ensure double 0 termination */
- uevent_next_event(uevent_desc, sizeof(uevent_desc) - 2);
- handle_uevents(hwc_dev, uevent_desc);
+ int len = uevent_next_event(uevent_desc, sizeof(uevent_desc) - 2);
+ handle_uevents(hwc_dev, uevent_desc, len);
}
} while (1);
@@ -1830,6 +1850,53 @@ static void omap4_hwc_registerProcs(struct hwc_composer_device* dev,
hwc_dev->procs = (typeof(hwc_dev->procs)) procs;
}
+static int omap4_hwc_query(struct hwc_composer_device* dev,
+ int what, int* value)
+{
+ omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) dev;
+
+ switch (what) {
+ case HWC_BACKGROUND_LAYER_SUPPORTED:
+ // we don't support the background layer yet
+ value[0] = 0;
+ break;
+ case HWC_VSYNC_PERIOD:
+ // vsync period in nanosecond
+ value[0] = 1000000000.0 / hwc_dev->fb_dev->base.fps;
+ break;
+ default:
+ // unsupported query
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int omap4_hwc_event_control(struct hwc_composer_device* dev,
+ int event, int enabled)
+{
+ omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) dev;
+
+ switch (event) {
+ case HWC_EVENT_VSYNC:
+ {
+ int val = !!enabled;
+ int err;
+
+ err = ioctl(hwc_dev->fb_fd, OMAPFB_ENABLEVSYNC, &val);
+ if (err < 0)
+ return -errno;
+
+ return 0;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+struct hwc_methods omap4_hwc_methods = {
+ .eventControl = &omap4_hwc_event_control,
+};
+
static int omap4_hwc_device_open(const hw_module_t* module, const char* name,
hw_device_t** device)
{
@@ -1860,13 +1927,15 @@ static int omap4_hwc_device_open(const hw_module_t* module, const char* name,
memset(hwc_dev, 0, sizeof(*hwc_dev));
hwc_dev->base.common.tag = HARDWARE_DEVICE_TAG;
- hwc_dev->base.common.version = HWC_DEVICE_API_VERSION;
+ hwc_dev->base.common.version = HWC_DEVICE_API_VERSION_0_3;
hwc_dev->base.common.module = (hw_module_t *)module;
hwc_dev->base.common.close = omap4_hwc_device_close;
hwc_dev->base.prepare = omap4_hwc_prepare;
hwc_dev->base.set = omap4_hwc_set;
hwc_dev->base.dump = omap4_hwc_dump;
hwc_dev->base.registerProcs = omap4_hwc_registerProcs;
+ hwc_dev->base.query = omap4_hwc_query;
+ hwc_dev->base.methods = &omap4_hwc_methods;
hwc_dev->fb_dev = hwc_mod->fb_dev;
*device = &hwc_dev->base.common;
@@ -2009,7 +2078,7 @@ omap4_hwc_module_t HAL_MODULE_INFO_SYM = {
.base = {
.common = {
.tag = HARDWARE_MODULE_TAG,
- .module_api_version = HWC_MODULE_API_VERSION,
+ .module_api_version = HWC_MODULE_API_VERSION_0_1,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = HWC_HARDWARE_MODULE_ID,
.name = "OMAP 44xx Hardware Composer HAL",