Import minigbm

Minigbm is a gbm implementation for a few DRM targets. Currently the
targets are:
- cirrus
- exynos
- gma500
- i915
- rockchip
- tegra
- udl

Right some targets are controlled with GBM_{TARGET} flags. I would
like to get to a place where we can just build all the targets in a
single library, but we need the drm headers for all targets for that
to happen so this needs more thinking.

BUG=chromium:394868,chromium:402597,chromium:413947,chromium:412508
TEST=unit tests, which I will need to import later

Signed-off-by: Stéphane Marchesin <marcheu@chromium.org>
Change-Id: I36ae07f2a59827a807e19e1432891ca196b28803
Reviewed-on: https://chromium-review.googlesource.com/218030
diff --git a/i915.c b/i915.c
new file mode 100644
index 0000000..6daee56
--- /dev/null
+++ b/i915.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifdef GBM_I915
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <xf86drm.h>
+#include <i915_drm.h>
+
+#include "gbm_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+struct gbm_i915_device
+{
+	int gen;
+};
+
+
+static int get_gen(int device_id)
+{
+	const uint16_t gen3_ids[] = {0x2582, 0x2592, 0x2772, 0x27A2, 0x27AE, 0x29C2, 0x29B2, 0x29D2, 0xA001, 0xA011};
+	int i;
+	for(i = 0; i < ARRAY_SIZE(gen3_ids); i++)
+		if (gen3_ids[i] == device_id)
+			return 3;
+
+	return 4;
+}
+
+int gbm_i915_init(struct gbm_device *gbm)
+{
+	struct gbm_i915_device *i915_gbm;
+	drm_i915_getparam_t get_param;
+	int device_id;
+	int ret;
+
+	i915_gbm = (struct gbm_i915_device*)malloc(sizeof(*i915_gbm));
+	if (!i915_gbm)
+		return -1;
+
+	memset(&get_param, 0, sizeof(get_param));
+	get_param.param = I915_PARAM_CHIPSET_ID;
+	get_param.value = &device_id;
+	ret = drmIoctl(gbm->fd, DRM_IOCTL_I915_GETPARAM, &get_param);
+	if (ret) {
+		free(i915_gbm);
+		return -1;
+	}
+
+	i915_gbm->gen = get_gen(device_id);
+
+	gbm->priv = i915_gbm;
+
+	return 0;
+}
+
+void gbm_i915_close(struct gbm_device *gbm)
+{
+	free(gbm->priv);
+	gbm->priv = NULL;
+}
+
+static int i915_get_pitch(struct gbm_device *gbm, uint32_t pitch, int tiling_mode)
+{
+	struct gbm_i915_device *dev_priv = (struct gbm_i915_device *)gbm->priv;
+	if (tiling_mode == I915_TILING_NONE)
+		return ALIGN(pitch, 64);
+
+	if (dev_priv->gen >= 4) {
+		uint32_t tile_width = tiling_mode == I915_TILING_X ? 512 : 128;
+		return ALIGN(pitch, tile_width);
+	} else {
+		uint32_t i = 128;
+		while(i < pitch)
+			i <<= 1;
+		return i;
+	}
+}
+
+int gbm_i915_bo_create(struct gbm_bo *bo, uint32_t width, uint32_t height, uint32_t format, uint32_t flags)
+{
+	size_t size = width * height * gbm_bytes_from_format(format);
+	struct drm_i915_gem_create gem_create;
+	struct drm_i915_gem_set_tiling gem_set_tiling;
+	uint32_t tiling_mode = I915_TILING_NONE;
+	int ret;
+
+	memset(&gem_create, 0, sizeof(gem_create));
+	gem_create.size = size;
+
+	ret = drmIoctl(bo->gbm->fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create);
+	if (ret)
+		return ret;
+
+	bo->handle.u32 = gem_create.handle;
+	bo->size = size;
+
+	if (flags & GBM_BO_USE_CURSOR)
+		tiling_mode = I915_TILING_NONE;
+	else if (flags & GBM_BO_USE_SCANOUT)
+		tiling_mode = I915_TILING_X;
+	else if (flags & GBM_BO_USE_RENDERING)
+		tiling_mode = I915_TILING_Y;
+
+	memset(&gem_set_tiling, 0, sizeof(gem_set_tiling));
+	do {
+		gem_set_tiling.handle = bo->handle.u32;
+		gem_set_tiling.tiling_mode = tiling_mode;
+		gem_set_tiling.stride = i915_get_pitch(bo->gbm,
+							width * gbm_bytes_from_format(format),
+							tiling_mode);
+		ret = drmIoctl(bo->gbm->fd, DRM_IOCTL_I915_GEM_SET_TILING, &gem_set_tiling);
+	} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
+
+	if (ret == -1) {
+		struct drm_gem_close gem_close;
+		gem_close.handle = bo->handle.u32;
+		drmIoctl(bo->gbm->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
+		return -errno;
+	}
+
+	return 0;
+}
+
+const struct gbm_driver gbm_driver_i915 =
+{
+	.name = "i915",
+	.init = gbm_i915_init,
+	.close = gbm_i915_close,
+	.bo_create = gbm_i915_bo_create,
+	.bo_destroy = gbm_gem_bo_destroy,
+	.format_list = {
+		{GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+		{GBM_FORMAT_ARGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+		{GBM_FORMAT_XBGR8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+		{GBM_FORMAT_ABGR8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+		{GBM_FORMAT_XRGB1555, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+		{GBM_FORMAT_ARGB1555, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+		{GBM_FORMAT_RGB565,   GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+	}
+};
+
+#endif