summaryrefslogtreecommitdiff
path: root/drmresources.cpp
diff options
context:
space:
mode:
authorSean Paul <seanpaul@chromium.org>2015-06-03 14:08:27 -0400
committerSean Paul <seanpaul@chromium.org>2015-06-15 16:30:48 -0400
commit877be974a2d4fc518700be8ffe803a50cb716ead (patch)
treefd3bb735012580ddaf2edf31ffd31b1083bb6117 /drmresources.cpp
parent1f4ff5aec7bec305558228adb65ba56bd0b9f366 (diff)
drm_hwcomposer: Use atomic modeset to set crtc timing
Use the new drm blob ioctl and atomic modeset properties to do atomic modesetting, as opposed to the old setCrtc call. This allows us to set timing as soon as the system layer requests a new active config, as opposed to delaying it until we have an fb. Aside from reducing complexity, this should help with event control requests as we'll be able to service them with hw vblanks instead of synthesized sleeps. Change-Id: I9c80d44f52f52881a3a25b2ae518973d468bc110 Signed-off-by: Sean Paul <seanpaul@chromium.org>
Diffstat (limited to 'drmresources.cpp')
-rw-r--r--drmresources.cpp165
1 files changed, 135 insertions, 30 deletions
diff --git a/drmresources.cpp b/drmresources.cpp
index 3429abc..2cda217 100644
--- a/drmresources.cpp
+++ b/drmresources.cpp
@@ -101,7 +101,7 @@ int DrmResources::Init() {
break;
}
- DrmCrtc *crtc = new DrmCrtc(c, i);
+ DrmCrtc *crtc = new DrmCrtc(this, c, i);
drmModeFreeCrtc(c);
@@ -110,6 +110,13 @@ int DrmResources::Init() {
ret = -ENOMEM;
break;
}
+
+ ret = crtc->Init();
+ if (ret) {
+ ALOGE("Failed to initialize crtc %d", res->crtcs[i]);
+ delete crtc;
+ break;
+ }
crtcs_.push_back(crtc);
}
@@ -315,43 +322,143 @@ int DrmResources::TryEncoderForDisplay(int display, DrmEncoder *enc) {
return -EAGAIN;
}
-int DrmResources::SetDisplayActiveMode(int display, uint32_t mode_id) {
- DrmEncoder *enc;
- int ret;
-
- DrmConnector *con = GetConnectorForDisplay(display);
- if (!con) {
- ALOGE("Could not locate connector for display %d", display);
- return -ENODEV;
- }
-
+int DrmResources::CreateDisplayPipe(DrmConnector *connector) {
+ int display = connector->display();
/* Try to use current setup first */
- enc = con->encoder();
- if (enc) {
- ret = TryEncoderForDisplay(display, enc);
+ if (connector->encoder()) {
+ int ret = TryEncoderForDisplay(display, connector->encoder());
if (!ret) {
- con->set_encoder(enc);
- return con->set_active_mode(mode_id);
+ return 0;
} else if (ret != -EAGAIN) {
ALOGE("Could not set mode %d/%d", display, ret);
return ret;
}
}
- for (DrmConnector::EncoderIter iter = con->begin_possible_encoders();
- iter != con->end_possible_encoders(); ++iter) {
- ret = TryEncoderForDisplay(display, *iter);
+ for (DrmConnector::EncoderIter iter = connector->begin_possible_encoders();
+ iter != connector->end_possible_encoders(); ++iter) {
+ int ret = TryEncoderForDisplay(display, *iter);
if (!ret) {
- con->set_encoder(*iter);
- return con->set_active_mode(mode_id);
+ connector->set_encoder(*iter);
+ return 0;
} else if (ret != -EAGAIN) {
ALOGE("Could not set mode %d/%d", display, ret);
return ret;
}
}
+ ALOGE("Could not find a suitable encoder/crtc for display %d",
+ connector->display());
+ return -ENODEV;
+}
+
+int DrmResources::CreatePropertyBlob(void *data, size_t length,
+ uint32_t *blob_id) {
+ struct drm_mode_create_blob create_blob;
+ memset(&create_blob, 0, sizeof(create_blob));
+ create_blob.length = length;
+ create_blob.data = (__u64)data;
+
+ int ret = drmIoctl(fd_, DRM_IOCTL_MODE_CREATEPROPBLOB, &create_blob);
+ if (ret) {
+ ALOGE("Failed to create mode property blob %d", ret);
+ return ret;
+ }
+ *blob_id = create_blob.blob_id;
+ return 0;
+}
+
+int DrmResources::DestroyPropertyBlob(uint32_t blob_id) {
+ struct drm_mode_destroy_blob destroy_blob;
+ memset(&destroy_blob, 0, sizeof(destroy_blob));
+ destroy_blob.blob_id = (__u32)blob_id;
+ int ret = drmIoctl(fd_, DRM_IOCTL_MODE_DESTROYPROPBLOB, &destroy_blob);
+ if (ret) {
+ ALOGE("Failed to destroy mode property blob %d", ret);
+ return ret;
+ }
+ return 0;
+}
+
+int DrmResources::SetDisplayActiveMode(int display, const DrmMode &mode) {
+ DrmConnector *connector = GetConnectorForDisplay(display);
+ if (!connector) {
+ ALOGE("Could not locate connector for display %d", display);
+ return -ENODEV;
+ }
+
+ int ret = CreateDisplayPipe(connector);
+ if (ret) {
+ ALOGE("Failed CreateDisplayPipe with %d", ret);
+ return ret;
+ }
+
+ DrmCrtc *crtc = connector->encoder()->crtc();
+ DrmProperty old_mode;
+ ret = GetCrtcProperty(*crtc, crtc->mode_property().name().c_str(), &old_mode);
+ if (ret) {
+ ALOGE("Failed to get old mode property from crtc %d", crtc->id());
+ return ret;
+ }
+
+ struct drm_mode_modeinfo drm_mode;
+ memset(&drm_mode, 0, sizeof(drm_mode));
+ mode.ToDrmModeModeInfo(&drm_mode);
+
+ uint32_t blob_id;
+ ret =
+ CreatePropertyBlob(&drm_mode, sizeof(struct drm_mode_modeinfo), &blob_id);
+ if (ret) {
+ ALOGE("Failed to create mode property blob %d", ret);
+ return ret;
+ }
+
+ drmModePropertySetPtr pset = drmModePropertySetAlloc();
+ if (!pset) {
+ ALOGE("Failed to allocate property set");
+ DestroyPropertyBlob(blob_id);
+ return -ENOMEM;
+ }
- ALOGE("Could not find a suitable encoder/crtc for display %d", display);
- return -EINVAL;
+ ret = drmModePropertySetAdd(pset, crtc->id(), crtc->mode_property().id(),
+ blob_id) ||
+ drmModePropertySetAdd(pset, connector->id(),
+ connector->crtc_id_property().id(), crtc->id());
+ if (ret) {
+ ALOGE("Failed to add blob %d to pset", blob_id);
+ DestroyPropertyBlob(blob_id);
+ drmModePropertySetFree(pset);
+ return ret;
+ }
+
+ ret =
+ drmModePropertySetCommit(fd_, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL, pset);
+
+ drmModePropertySetFree(pset);
+
+ if (ret) {
+ ALOGE("Failed to commit pset ret=%d\n", ret);
+ DestroyPropertyBlob(blob_id);
+ return ret;
+ }
+
+ connector->set_active_mode(mode);
+
+ uint64_t old_blob_id;
+ ret = old_mode.value(&old_blob_id);
+ if (ret) {
+ ALOGE("Could not get old blob id value %d", ret);
+ return ret;
+ }
+ if (!old_blob_id)
+ return 0;
+
+ ret = DestroyPropertyBlob(old_blob_id);
+ if (ret) {
+ ALOGE("Failed to destroy old mode property blob", old_blob_id);
+ return ret;
+ }
+
+ return 0;
}
int DrmResources::SetDpmsMode(int display, uint64_t mode) {
@@ -360,13 +467,6 @@ int DrmResources::SetDpmsMode(int display, uint64_t mode) {
return -EINVAL;
}
- DrmCrtc *crtc = GetCrtcForDisplay(display);
- if (!crtc) {
- ALOGE("Failed to get DrmCrtc for display %d", display);
- return -ENODEV;
- }
- crtc->set_requires_modeset(true);
-
DrmConnector *c = GetConnectorForDisplay(display);
if (!c) {
ALOGE("Failed to get DrmConnector for display %d", display);
@@ -416,6 +516,11 @@ int DrmResources::GetPlaneProperty(const DrmPlane &plane, const char *prop_name,
return GetProperty(plane.id(), DRM_MODE_OBJECT_PLANE, prop_name, property);
}
+int DrmResources::GetCrtcProperty(const DrmCrtc &crtc, const char *prop_name,
+ DrmProperty *property) {
+ return GetProperty(crtc.id(), DRM_MODE_OBJECT_CRTC, prop_name, property);
+}
+
int DrmResources::GetConnectorProperty(const DrmConnector &connector,
const char *prop_name,
DrmProperty *property) {