diff options
author | Sean Paul <seanpaul@chromium.org> | 2015-10-26 15:37:06 -0400 |
---|---|---|
committer | Sean Paul <seanpaul@chromium.org> | 2016-03-29 13:56:13 -0400 |
commit | 3a69f73205d4da12c1de16d06d0589e443a65812 (patch) | |
tree | c5fb69f32e38a25c70e737e53f4031e24f8faf41 /hwcomposer.cpp | |
parent | 55584b51b27481f7219c7c95a0a6350f43443457 (diff) | |
download | drm_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.cpp | 66 |
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]) { |