summaryrefslogtreecommitdiff
path: root/v4l2-mfc-example/drm.c
diff options
context:
space:
mode:
Diffstat (limited to 'v4l2-mfc-example/drm.c')
-rw-r--r--v4l2-mfc-example/drm.c164
1 files changed, 164 insertions, 0 deletions
diff --git a/v4l2-mfc-example/drm.c b/v4l2-mfc-example/drm.c
new file mode 100644
index 0000000..188d394
--- /dev/null
+++ b/v4l2-mfc-example/drm.c
@@ -0,0 +1,164 @@
+/*
+ * V4L2 Codec decoding example application
+ * Kamil Debski <k.debski@samsung.com>
+ *
+ * DRM operations
+ *
+ * Copyright 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "drm.h"
+#include <string.h>
+
+#ifdef DRM
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+#include <exynos_drm.h>
+
+int drm_open(struct instance *i, char *name)
+{
+ char mode[32];
+ drmModeCrtc *crtc;
+ struct drm_gem_close args;
+ drmModeConnector *connector;
+ drmModeModeInfo *mode_drm;
+ unsigned int fb_id;
+ int ret;
+ int n;
+
+ i->drm.fd =drmOpen(name, NULL);
+ if (i->drm.fd < 0) {
+ err("Failed to open drm module \"%s\"", name);
+ return -1;
+ }
+
+ i->drm.resources = drmModeGetResources(i->drm.fd);
+
+ crtc = drmModeGetCrtc(i->drm.fd, i->drm.crtc_id);
+ if (!crtc) {
+ err("Failed to get crtc: %d", i->drm.crtc_id);
+ return -1;
+ }
+
+ i->drm.width = crtc->width;
+ i->drm.height = crtc->height;
+
+ dbg("DRM crtc (%d) resolution: %dx%d @", i->drm.crtc_id, i->drm.width,
+ i->drm.height);
+ drmModeFreeCrtc(crtc);
+
+ for (n = 0; n < (i->fimc.double_buf?2:1); n++) {
+ i->drm.gem[n].size = i->drm.width * i->drm.height * 4;
+ ret = ioctl(i->drm.fd, DRM_IOCTL_EXYNOS_GEM_CREATE,
+ &i->drm.gem[n]);
+ if (ret < 0) {
+ err("Failed to create gem");
+ return -1;
+ }
+ args.handle = i->drm.gem[n].handle;
+ i->drm.mmap[n].handle = i->drm.gem[n].handle;
+ i->drm.mmap[n].size = i->drm.gem[n].size;
+ ret = ioctl(i->drm.fd, DRM_IOCTL_EXYNOS_GEM_MMAP, &i->drm.mmap[n]);
+ if (ret < 0) {
+ ioctl(i->drm.fd, DRM_IOCTL_GEM_CLOSE, &args);
+ err("Failed to mmap gem");
+ return -1;
+ }
+ ret = drmModeAddFB(i->drm.fd, i->drm.width, i->drm.height, 32,
+ 32, 4 * i->drm.width, i->drm.gem[n].handle, &fb_id);
+ if (ret) {
+ munmap((void *)(unsigned long)i->drm.mmap[n].mapped,
+ i->drm.gem[n].size);
+ ioctl(i->drm.fd, DRM_IOCTL_GEM_CLOSE, &args);
+ err("Failed to add fb");
+ return -1;
+ }
+ i->drm.fb[n] = fb_id;
+ i->drm.p[n] = (char *)(unsigned int)i->drm.mmap[n].mapped;
+ i->fimc.p[n] = (char *)(unsigned int)i->drm.mmap[n].mapped;
+ }
+
+ snprintf(mode, 32, "%dx%d", crtc->width, crtc->height);
+
+ connector = drmModeGetConnector(i->drm.fd, i->drm.conn_id);
+ if (!connector || connector->connector_id != i->drm.conn_id) {
+ err("Couldn't find the connector");
+ drmModeFreeConnector(connector);
+ return -1;
+ }
+
+ mode_drm = 0;
+
+ for (n = 0; n < connector->count_modes; n++) {
+ if (!strncmp(connector->modes[n].name, mode, 32)) {
+ mode_drm = &connector->modes[n];
+ break;
+ }
+ }
+
+ if (!mode_drm) {
+ err("Failed to find mode\n");
+ drmModeFreeConnector(connector);
+ return -1;
+ }
+
+ ret = drmModeSetCrtc(i->drm.fd, i->drm.crtc_id, i->drm.fb[0], 0, 0,
+ &i->drm.conn_id, 1, mode_drm);
+ if (ret) {
+ err("Failed to set crtc");
+ drmModeFreeConnector(connector);
+ return -1;
+ }
+
+ i->fimc.width = i->drm.width;
+ i->fimc.height = i->drm.height;
+ i->fimc.stride = i->drm.width * 4;
+ i->fimc.bpp = 32;
+ i->fimc.buffers = (i->fimc.double_buf?2:1);
+ i->fimc.size = i->drm.width * i->drm.height * 4;
+
+ i->drm.crtc[0] = i->drm.crtc_id;
+ i->drm.crtc[1] = i->drm.crtc_id;
+
+ return 0;
+}
+
+void drm_close(struct instance *i)
+{
+ drmClose(i->drm.fd);
+}
+
+#else /* DRM */
+
+int drm_open(struct instance *i, char *name)
+{
+ return 0;
+};
+
+void drm_close(struct instance *i) {
+ return;
+}
+
+#endif /* DRM */