aboutsummaryrefslogtreecommitdiff
path: root/hwcomposer.cpp
diff options
context:
space:
mode:
authorSean Paul <seanpaul@chromium.org>2015-10-26 15:37:06 -0400
committerSean Paul <seanpaul@chromium.org>2016-03-29 13:56:13 -0400
commit3a69f73205d4da12c1de16d06d0589e443a65812 (patch)
treec5fb69f32e38a25c70e737e53f4031e24f8faf41 /hwcomposer.cpp
parent55584b51b27481f7219c7c95a0a6350f43443457 (diff)
downloaddrm_hwcomposer-3a69f73205d4da12c1de16d06d0589e443a65812.tar.gz
drm_hwcomposer: Add hotplug event handler
Add a hotplug event handler to handle hotplug events. Upon hotplug, the handler is responsible for finding and setting the preferred mode of the new display. BUG=chrome-os-partner:41682 TEST=Tested on ryu with DP Change-Id: Ide57382624c7839ed81a712bc29ea2e1cc19dcae Signed-off-by: Sean Paul <seanpaul@chromium.org>
Diffstat (limited to 'hwcomposer.cpp')
-rw-r--r--hwcomposer.cpp66
1 files changed, 66 insertions, 0 deletions
diff --git a/hwcomposer.cpp b/hwcomposer.cpp
index efc9b95..0e0444b 100644
--- a/hwcomposer.cpp
+++ b/hwcomposer.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "hwcomposer-drm"
#include "drmhwcomposer.h"
+#include "drmeventlistener.h"
#include "drmresources.h"
#include "importer.h"
#include "virtualcompositorworker.h"
@@ -25,6 +26,7 @@
#include <stdlib.h>
+#include <cinttypes>
#include <map>
#include <vector>
#include <sstream>
@@ -124,6 +126,62 @@ typedef struct hwc_drm_display {
VSyncWorker vsync_worker;
} hwc_drm_display_t;
+class DrmHotplugHandler : public DrmEventHandler {
+ public:
+ void Init(DrmResources *drm, const struct hwc_procs *procs) {
+ drm_ = drm;
+ procs_ = procs;
+ }
+
+ void HandleEvent(uint64_t timestamp_us) {
+ for (auto &conn : drm_->connectors()) {
+ drmModeConnection old_state = conn->state();
+
+ conn->UpdateModes();
+
+ drmModeConnection cur_state = conn->state();
+
+ if (cur_state == old_state)
+ continue;
+
+ ALOGI("%s event @%" PRIu64 " for connector %u\n",
+ cur_state == DRM_MODE_CONNECTED ? "Plug" : "Unplug", timestamp_us,
+ conn->id());
+
+ if (cur_state == DRM_MODE_CONNECTED) {
+ // Take the first one, then look for the preferred
+ DrmMode mode = *(conn->modes().begin());
+ for (auto &m : conn->modes()) {
+ if (m.type() & DRM_MODE_TYPE_PREFERRED) {
+ mode = m;
+ break;
+ }
+ }
+ ALOGI("Setting mode %dx%d for connector %d\n", mode.h_display(),
+ mode.v_display(), conn->id());
+ int ret = drm_->SetDisplayActiveMode(conn->display(), mode);
+ if (ret) {
+ ALOGE("Failed to set active config %d", ret);
+ return;
+ }
+ } else {
+ int ret = drm_->SetDpmsMode(conn->display(), DRM_MODE_DPMS_OFF);
+ if (ret) {
+ ALOGE("Failed to set dpms mode off %d", ret);
+ return;
+ }
+ }
+
+ procs_->hotplug(procs_, conn->display(),
+ cur_state == DRM_MODE_CONNECTED ? 1 : 0);
+ }
+ }
+
+ private:
+ DrmResources *drm_ = NULL;
+ const struct hwc_procs *procs_ = NULL;
+};
+
struct hwc_context_t {
// map of display:hwc_drm_display_t
typedef std::map<int, hwc_drm_display_t> DisplayMap;
@@ -141,6 +199,7 @@ struct hwc_context_t {
const gralloc_module_t *gralloc;
DummySwSyncTimeline dummy_timeline;
VirtualCompositorWorker virtual_compositor_worker;
+ DrmHotplugHandler hotplug_handler;
};
static native_handle_t *dup_buffer_handle(buffer_handle_t handle) {
@@ -626,6 +685,9 @@ static void hwc_register_procs(struct hwc_composer_device_1 *dev,
for (std::pair<const int, hwc_drm_display> &display_entry : ctx->displays)
display_entry.second.vsync_worker.SetProcs(procs);
+
+ ctx->hotplug_handler.Init(&ctx->drm, procs);
+ ctx->drm.event_listener()->RegisterHotplugHandler(&ctx->hotplug_handler);
}
static int hwc_get_display_configs(struct hwc_composer_device_1 *dev,
@@ -742,6 +804,10 @@ static int hwc_set_active_config(struct hwc_composer_device_1 *dev, int display,
ALOGE("Failed to get connector for display %d", display);
return -ENODEV;
}
+
+ if (c->state() != DRM_MODE_CONNECTED)
+ return -ENODEV;
+
DrmMode mode;
for (const DrmMode &conn_mode : c->modes()) {
if (conn_mode.id() == hd->config_ids[index]) {