Merge tag libdrm-2.4.75 into aosp/master
Below is a brief summary of patches pulled in:
0da99b8a (m/master, aosp/master) Move libdrm.so to vendor partition
d4b83443 (tag: libdrm-2.4.75) Bump version for 2.4.75 release
dae413e4 (tag: libdrm-2.4.74) Bump version for release
317bdff1 (tag: libdrm-2.4.73) Bump version for release
8cf43127 (tag: libdrm-2.4.72) Bump version for release
a44c9c31 (tag: libdrm-2.4.71) Bump version for release
20208455 (tag: android-o-preview-1, tag: android-n-mr2-preview-2, tag:
android-n-mr2-preview-1, aosp/sdk-release, aosp/o-preview) add a flag
control that private libdrm can be chosen
Bug: 35871718
Test: aosp_arm-eng compiles
Change-Id: I81985fd41d5c0d8a732705dc2a4bee8eb5d459bb
diff --git a/Android.mk b/Android.mk
index 5209059..102c9a3 100644
--- a/Android.mk
+++ b/Android.mk
@@ -21,19 +21,28 @@
# IN THE SOFTWARE.
#
+
+ifneq ($(TARGET_USE_PRIVATE_LIBDRM),true)
+
LIBDRM_COMMON_MK := $(call my-dir)/Android.common.mk
LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
# Import variables LIBDRM_{,H_,INCLUDE_H_,INCLUDE_VMWGFX_H_}FILES
include $(LOCAL_PATH)/Makefile.sources
-#static library for the device (recovery)
+common_CFLAGS := \
+ -Wno-enum-conversion \
+ -Wno-pointer-arith \
+ -Wno-sign-compare \
+ -Wno-tautological-compare
+
+# Static library for the device (recovery)
include $(CLEAR_VARS)
+
LOCAL_MODULE := libdrm
-LOCAL_SRC_FILES := $(LIBDRM_FILES)
+LOCAL_SRC_FILES := $(filter-out %.h,$(LIBDRM_FILES))
LOCAL_EXPORT_C_INCLUDE_DIRS := \
$(LOCAL_PATH) \
$(LOCAL_PATH)/include/drm
@@ -41,21 +50,31 @@
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/include/drm
+LOCAL_CFLAGS := \
+ $(common_CFLAGS)
+
include $(LIBDRM_COMMON_MK)
include $(BUILD_STATIC_LIBRARY)
-# Shared library for the device
+# Dynamic library for the device
include $(CLEAR_VARS)
-LOCAL_MODULE := libdrm
-LOCAL_SRC_FILES := $(LIBDRM_FILES)
+LOCAL_MODULE := libdrm
+LOCAL_VENDOR_MODULE := true
+
+LOCAL_SRC_FILES := $(filter-out %.h,$(LIBDRM_FILES))
LOCAL_EXPORT_C_INCLUDE_DIRS := \
- $(LOCAL_PATH)/include/drm
+ $(LOCAL_PATH) \
+ $(LOCAL_PATH)/include/drm
LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/include/drm
+ $(LOCAL_PATH)/include/drm
+
+LOCAL_CFLAGS := \
+ $(common_CFLAGS)
include $(LIBDRM_COMMON_MK)
include $(BUILD_SHARED_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))
+endif
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 28a11db..aa1d752 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -2,3 +2,7 @@
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/include/freedreno)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libdrm_*intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libdrm_*intermediates)
+
+# libdrm is moved from /system to /vendor
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libdrm.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/libdrm.so)
diff --git a/Makefile.am b/Makefile.am
index dfb8fcd..2bf644b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -96,6 +96,10 @@
endif
endif
+if HAVE_ROCKCHIP
+ROCKCHIP_SUBDIR = rockchip
+endif
+
SUBDIRS = \
. \
$(LIBKMS_SUBDIR) \
@@ -110,7 +114,8 @@
$(VC4_SUBDIR) \
$(ETNAVIV_SUBDIR) \
tests \
- $(MAN_SUBDIR)
+ $(MAN_SUBDIR) \
+ $(ROCKCHIP_SUBDIR)
libdrm_la_LTLIBRARIES = libdrm.la
libdrm_ladir = $(libdir)
diff --git a/configure.ac b/configure.ac
index 8e59332..1da9d86 100644
--- a/configure.ac
+++ b/configure.ac
@@ -127,6 +127,11 @@
[Enable support for Tegra's experimental API (default: disabled)]),
[TEGRA=$enableval], [TEGRA=no])
+AC_ARG_ENABLE(rockchip-experimental-api,
+ AS_HELP_STRING([--enable-rockchip-experimental-api],
+ [Enable support for rockchip's experimental API (default: disabled)]),
+ [ROCKCHIP=$enableval], [ROCKCHIP=no])
+
AC_ARG_ENABLE(vc4,
AS_HELP_STRING([--disable-vc4],
[Enable support for vc4's API (default: auto, enabled on arm)]),
@@ -416,6 +421,10 @@
AC_DEFINE(HAVE_TEGRA, 1, [Have Tegra support])
fi
+AM_CONDITIONAL(HAVE_ROCKCHIP, [test "x$ROCKCHIP" = xyes])
+if test "x$ROCKCHIP" = xyes; then
+ AC_DEFINE(HAVE_ROCKCHIP, 1, [Have ROCKCHIP support])
+
AM_CONDITIONAL(HAVE_VC4, [test "x$VC4" = xyes])
if test "x$VC4" = xyes; then
AC_DEFINE(HAVE_VC4, 1, [Have VC4 support])
@@ -528,6 +537,8 @@
freedreno/libdrm_freedreno.pc
tegra/Makefile
tegra/libdrm_tegra.pc
+ rockchip/Makefile
+ rockchip/libdrm_rockchip.pc
vc4/Makefile
vc4/libdrm_vc4.pc
etnaviv/Makefile
@@ -544,6 +555,7 @@
tests/exynos/Makefile
tests/tegra/Makefile
tests/nouveau/Makefile
+ tests/planetest/Makefile
tests/etnaviv/Makefile
tests/util/Makefile
man/Makefile
@@ -563,6 +575,7 @@
echo " EXYNOS API $EXYNOS"
echo " Freedreno API $FREEDRENO (kgsl: $FREEDRENO_KGSL)"
echo " Tegra API $TEGRA"
+echo " Rockchip API $ROCKCHIP"
echo " VC4 API $VC4"
echo " Etnaviv API $ETNAVIV"
echo ""
diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
index df0e350..6708e2b 100644
--- a/include/drm/drm_mode.h
+++ b/include/drm/drm_mode.h
@@ -107,6 +107,14 @@
#define DRM_MODE_DIRTY_ON 1
#define DRM_MODE_DIRTY_ANNOTATE 2
+/* rotation property bits */
+#define DRM_ROTATE_0 0
+#define DRM_ROTATE_90 1
+#define DRM_ROTATE_180 2
+#define DRM_ROTATE_270 3
+#define DRM_REFLECT_X 4
+#define DRM_REFLECT_Y 5
+
struct drm_mode_modeinfo {
__u32 clock;
__u16 hdisplay;
@@ -629,6 +637,13 @@
DRM_MODE_ATOMIC_NONBLOCK |\
DRM_MODE_ATOMIC_ALLOW_MODESET)
+#define DRM_MODE_ATOMIC_FLAGS (\
+ DRM_MODE_PAGE_FLIP_EVENT |\
+ DRM_MODE_PAGE_FLIP_ASYNC |\
+ DRM_MODE_ATOMIC_TEST_ONLY |\
+ DRM_MODE_ATOMIC_NONBLOCK |\
+ DRM_MODE_ATOMIC_ALLOW_MODESET)
+
struct drm_mode_atomic {
__u32 flags;
__u32 count_objs;
diff --git a/include/drm/nouveau_class.h b/include/drm/nouveau_class.h
new file mode 100644
index 0000000..8d63877
--- /dev/null
+++ b/include/drm/nouveau_class.h
@@ -0,0 +1,651 @@
+#ifndef __NVIF_CLASS_H__
+#define __NVIF_CLASS_H__
+
+/*******************************************************************************
+ * class identifiers
+ ******************************************************************************/
+
+/* the below match nvidia-assigned (either in hw, or sw) class numbers */
+#define NV_DEVICE 0x00000080
+
+#define NV_DMA_FROM_MEMORY 0x00000002
+#define NV_DMA_TO_MEMORY 0x00000003
+#define NV_DMA_IN_MEMORY 0x0000003d
+
+#define FERMI_TWOD_A 0x0000902d
+
+#define FERMI_MEMORY_TO_MEMORY_FORMAT_A 0x0000903d
+
+#define KEPLER_INLINE_TO_MEMORY_A 0x0000a040
+#define KEPLER_INLINE_TO_MEMORY_B 0x0000a140
+
+#define NV04_DISP 0x00000046
+
+#define NV03_CHANNEL_DMA 0x0000006b
+#define NV10_CHANNEL_DMA 0x0000006e
+#define NV17_CHANNEL_DMA 0x0000176e
+#define NV40_CHANNEL_DMA 0x0000406e
+#define NV50_CHANNEL_DMA 0x0000506e
+#define G82_CHANNEL_DMA 0x0000826e
+
+#define NV50_CHANNEL_GPFIFO 0x0000506f
+#define G82_CHANNEL_GPFIFO 0x0000826f
+#define FERMI_CHANNEL_GPFIFO 0x0000906f
+#define KEPLER_CHANNEL_GPFIFO_A 0x0000a06f
+#define MAXWELL_CHANNEL_GPFIFO_A 0x0000b06f
+
+#define NV50_DISP 0x00005070
+#define G82_DISP 0x00008270
+#define GT200_DISP 0x00008370
+#define GT214_DISP 0x00008570
+#define GT206_DISP 0x00008870
+#define GF110_DISP 0x00009070
+#define GK104_DISP 0x00009170
+#define GK110_DISP 0x00009270
+#define GM107_DISP 0x00009470
+#define GM204_DISP 0x00009570
+
+#define NV50_DISP_CURSOR 0x0000507a
+#define G82_DISP_CURSOR 0x0000827a
+#define GT214_DISP_CURSOR 0x0000857a
+#define GF110_DISP_CURSOR 0x0000907a
+#define GK104_DISP_CURSOR 0x0000917a
+
+#define NV50_DISP_OVERLAY 0x0000507b
+#define G82_DISP_OVERLAY 0x0000827b
+#define GT214_DISP_OVERLAY 0x0000857b
+#define GF110_DISP_OVERLAY 0x0000907b
+#define GK104_DISP_OVERLAY 0x0000917b
+
+#define NV50_DISP_BASE_CHANNEL_DMA 0x0000507c
+#define G82_DISP_BASE_CHANNEL_DMA 0x0000827c
+#define GT200_DISP_BASE_CHANNEL_DMA 0x0000837c
+#define GT214_DISP_BASE_CHANNEL_DMA 0x0000857c
+#define GF110_DISP_BASE_CHANNEL_DMA 0x0000907c
+#define GK104_DISP_BASE_CHANNEL_DMA 0x0000917c
+#define GK110_DISP_BASE_CHANNEL_DMA 0x0000927c
+
+#define NV50_DISP_CORE_CHANNEL_DMA 0x0000507d
+#define G82_DISP_CORE_CHANNEL_DMA 0x0000827d
+#define GT200_DISP_CORE_CHANNEL_DMA 0x0000837d
+#define GT214_DISP_CORE_CHANNEL_DMA 0x0000857d
+#define GT206_DISP_CORE_CHANNEL_DMA 0x0000887d
+#define GF110_DISP_CORE_CHANNEL_DMA 0x0000907d
+#define GK104_DISP_CORE_CHANNEL_DMA 0x0000917d
+#define GK110_DISP_CORE_CHANNEL_DMA 0x0000927d
+#define GM107_DISP_CORE_CHANNEL_DMA 0x0000947d
+#define GM204_DISP_CORE_CHANNEL_DMA 0x0000957d
+
+#define NV50_DISP_OVERLAY_CHANNEL_DMA 0x0000507e
+#define G82_DISP_OVERLAY_CHANNEL_DMA 0x0000827e
+#define GT200_DISP_OVERLAY_CHANNEL_DMA 0x0000837e
+#define GT214_DISP_OVERLAY_CHANNEL_DMA 0x0000857e
+#define GF110_DISP_OVERLAY_CONTROL_DMA 0x0000907e
+#define GK104_DISP_OVERLAY_CONTROL_DMA 0x0000917e
+
+#define FERMI_A 0x00009097
+#define FERMI_B 0x00009197
+#define FERMI_C 0x00009297
+
+#define KEPLER_A 0x0000a097
+#define KEPLER_B 0x0000a197
+#define KEPLER_C 0x0000a297
+
+#define MAXWELL_A 0x0000b097
+#define MAXWELL_B 0x0000b197
+
+#define FERMI_COMPUTE_A 0x000090c0
+#define FERMI_COMPUTE_B 0x000091c0
+
+#define KEPLER_COMPUTE_A 0x0000a0c0
+#define KEPLER_COMPUTE_B 0x0000a1c0
+
+#define MAXWELL_COMPUTE_A 0x0000b0c0
+#define MAXWELL_COMPUTE_B 0x0000b1c0
+
+#define MAXWELL_DMA_COPY_A 0x0000b0b5
+
+/*******************************************************************************
+ * client
+ ******************************************************************************/
+
+#define NV_CLIENT_DEVLIST 0x00
+
+struct nv_client_devlist_v0 {
+ __u8 version;
+ __u8 count;
+ __u8 pad02[6];
+ __u64 device[];
+};
+
+
+/*******************************************************************************
+ * device
+ ******************************************************************************/
+
+struct nv_device_v0 {
+ __u8 version;
+ __u8 pad01[7];
+ __u64 device; /* device identifier, ~0 for client default */
+#define NV_DEVICE_V0_DISABLE_IDENTIFY 0x0000000000000001ULL
+#define NV_DEVICE_V0_DISABLE_MMIO 0x0000000000000002ULL
+#define NV_DEVICE_V0_DISABLE_VBIOS 0x0000000000000004ULL
+#define NV_DEVICE_V0_DISABLE_CORE 0x0000000000000008ULL
+#define NV_DEVICE_V0_DISABLE_DISP 0x0000000000010000ULL
+#define NV_DEVICE_V0_DISABLE_FIFO 0x0000000000020000ULL
+#define NV_DEVICE_V0_DISABLE_GR 0x0000000100000000ULL
+#define NV_DEVICE_V0_DISABLE_MPEG 0x0000000200000000ULL
+#define NV_DEVICE_V0_DISABLE_ME 0x0000000400000000ULL
+#define NV_DEVICE_V0_DISABLE_VP 0x0000000800000000ULL
+#define NV_DEVICE_V0_DISABLE_CIPHER 0x0000001000000000ULL
+#define NV_DEVICE_V0_DISABLE_BSP 0x0000002000000000ULL
+#define NV_DEVICE_V0_DISABLE_MSPPP 0x0000004000000000ULL
+#define NV_DEVICE_V0_DISABLE_CE0 0x0000008000000000ULL
+#define NV_DEVICE_V0_DISABLE_CE1 0x0000010000000000ULL
+#define NV_DEVICE_V0_DISABLE_VIC 0x0000020000000000ULL
+#define NV_DEVICE_V0_DISABLE_MSENC 0x0000040000000000ULL
+#define NV_DEVICE_V0_DISABLE_CE2 0x0000080000000000ULL
+#define NV_DEVICE_V0_DISABLE_MSVLD 0x0000100000000000ULL
+#define NV_DEVICE_V0_DISABLE_SEC 0x0000200000000000ULL
+#define NV_DEVICE_V0_DISABLE_MSPDEC 0x0000400000000000ULL
+ __u64 disable; /* disable particular subsystems */
+ __u64 debug0; /* as above, but *internal* ids, and *NOT* ABI */
+};
+
+#define NV_DEVICE_V0_INFO 0x00
+#define NV_DEVICE_V0_ZCULL_INFO 0x01
+
+struct nv_device_info_v0 {
+ __u8 version;
+#define NV_DEVICE_INFO_V0_IGP 0x00
+#define NV_DEVICE_INFO_V0_PCI 0x01
+#define NV_DEVICE_INFO_V0_AGP 0x02
+#define NV_DEVICE_INFO_V0_PCIE 0x03
+#define NV_DEVICE_INFO_V0_SOC 0x04
+ __u8 platform;
+ __u16 chipset; /* from NV_PMC_BOOT_0 */
+ __u8 revision; /* from NV_PMC_BOOT_0 */
+#define NV_DEVICE_INFO_V0_TNT 0x01
+#define NV_DEVICE_INFO_V0_CELSIUS 0x02
+#define NV_DEVICE_INFO_V0_KELVIN 0x03
+#define NV_DEVICE_INFO_V0_RANKINE 0x04
+#define NV_DEVICE_INFO_V0_CURIE 0x05
+#define NV_DEVICE_INFO_V0_TESLA 0x06
+#define NV_DEVICE_INFO_V0_FERMI 0x07
+#define NV_DEVICE_INFO_V0_KEPLER 0x08
+#define NV_DEVICE_INFO_V0_MAXWELL 0x09
+ __u8 family;
+ __u8 pad06[2];
+ __u64 ram_size;
+ __u64 ram_user;
+};
+
+struct nv_device_zcull_info_v0 {
+ __u8 version;
+ __u8 pad03[3];
+ __u32 image_size;
+ __u32 width_align_pixels;
+ __u32 height_align_pixels;
+ __u32 pixel_squares_by_aliquots;
+ __u32 aliquot_total;
+ __u32 region_byte_multiplier;
+ __u32 region_header_size;
+ __u32 subregion_header_size;
+ __u32 subregion_width_align_pixels;
+ __u32 subregion_height_align_pixels;
+ __u32 subregion_count;
+};
+
+/*******************************************************************************
+ * context dma
+ ******************************************************************************/
+
+struct nv_dma_v0 {
+ __u8 version;
+#define NV_DMA_V0_TARGET_VM 0x00
+#define NV_DMA_V0_TARGET_VRAM 0x01
+#define NV_DMA_V0_TARGET_PCI 0x02
+#define NV_DMA_V0_TARGET_PCI_US 0x03
+#define NV_DMA_V0_TARGET_AGP 0x04
+ __u8 target;
+#define NV_DMA_V0_ACCESS_VM 0x00
+#define NV_DMA_V0_ACCESS_RD 0x01
+#define NV_DMA_V0_ACCESS_WR 0x02
+#define NV_DMA_V0_ACCESS_RDWR (NV_DMA_V0_ACCESS_RD | NV_DMA_V0_ACCESS_WR)
+ __u8 access;
+ __u8 pad03[5];
+ __u64 start;
+ __u64 limit;
+ /* ... chipset-specific class data */
+};
+
+struct nv50_dma_v0 {
+ __u8 version;
+#define NV50_DMA_V0_PRIV_VM 0x00
+#define NV50_DMA_V0_PRIV_US 0x01
+#define NV50_DMA_V0_PRIV__S 0x02
+ __u8 priv;
+#define NV50_DMA_V0_PART_VM 0x00
+#define NV50_DMA_V0_PART_256 0x01
+#define NV50_DMA_V0_PART_1KB 0x02
+ __u8 part;
+#define NV50_DMA_V0_COMP_NONE 0x00
+#define NV50_DMA_V0_COMP_1 0x01
+#define NV50_DMA_V0_COMP_2 0x02
+#define NV50_DMA_V0_COMP_VM 0x03
+ __u8 comp;
+#define NV50_DMA_V0_KIND_PITCH 0x00
+#define NV50_DMA_V0_KIND_VM 0x7f
+ __u8 kind;
+ __u8 pad05[3];
+};
+
+struct gf100_dma_v0 {
+ __u8 version;
+#define GF100_DMA_V0_PRIV_VM 0x00
+#define GF100_DMA_V0_PRIV_US 0x01
+#define GF100_DMA_V0_PRIV__S 0x02
+ __u8 priv;
+#define GF100_DMA_V0_KIND_PITCH 0x00
+#define GF100_DMA_V0_KIND_VM 0xff
+ __u8 kind;
+ __u8 pad03[5];
+};
+
+struct gf110_dma_v0 {
+ __u8 version;
+#define GF110_DMA_V0_PAGE_LP 0x00
+#define GF110_DMA_V0_PAGE_SP 0x01
+ __u8 page;
+#define GF110_DMA_V0_KIND_PITCH 0x00
+#define GF110_DMA_V0_KIND_VM 0xff
+ __u8 kind;
+ __u8 pad03[5];
+};
+
+
+/*******************************************************************************
+ * perfmon
+ ******************************************************************************/
+
+struct nvif_perfctr_v0 {
+ __u8 version;
+ __u8 pad01[1];
+ __u16 logic_op;
+ __u8 pad04[4];
+ char name[4][64];
+};
+
+#define NVIF_PERFCTR_V0_QUERY 0x00
+#define NVIF_PERFCTR_V0_SAMPLE 0x01
+#define NVIF_PERFCTR_V0_READ 0x02
+
+struct nvif_perfctr_query_v0 {
+ __u8 version;
+ __u8 pad01[3];
+ __u32 iter;
+ char name[64];
+};
+
+struct nvif_perfctr_sample {
+};
+
+struct nvif_perfctr_read_v0 {
+ __u8 version;
+ __u8 pad01[7];
+ __u32 ctr;
+ __u32 clk;
+};
+
+
+/*******************************************************************************
+ * device control
+ ******************************************************************************/
+
+#define NVIF_CONTROL_PSTATE_INFO 0x00
+#define NVIF_CONTROL_PSTATE_ATTR 0x01
+#define NVIF_CONTROL_PSTATE_USER 0x02
+
+struct nvif_ustate {
+ __s8 min;
+ __s8 max;
+};
+
+struct nvif_control_pstate_info_v0 {
+ __u8 version;
+ __u8 count; /* out: number of power states */
+#define NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE (-1)
+#define NVIF_CONTROL_PSTATE_INFO_V0_USTATE_PERFMON (-2)
+ struct {
+ struct nvif_ustate dc; // pwrsrc == 0
+ struct nvif_ustate ac; // pwrsrc == 1
+ } ustate; /* out: target pstate index */
+ __s8 pwrsrc; /* out: current power source */
+#define NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_UNKNOWN (-1)
+#define NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_PERFMON (-2)
+ __s8 pstate; /* out: current pstate index */
+ __u8 pad06[2];
+};
+
+struct nvif_control_pstate_attr_v0 {
+ __u8 version;
+#define NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT (-1)
+ __s8 state; /* in: index of pstate to query
+ * out: pstate identifier
+ */
+ __u8 index; /* in: index of attribute to query
+ * out: index of next attribute, or 0 if no more
+ */
+ __u8 pad03[5];
+ __u32 min;
+ __u32 max;
+ char name[32];
+ char unit[16];
+};
+
+struct nvif_control_pstate_user_v0 {
+ __u8 version;
+#define NVIF_CONTROL_PSTATE_USER_V0_STATE_UNKNOWN (-1)
+#define NVIF_CONTROL_PSTATE_USER_V0_STATE_PERFMON (-2)
+ struct nvif_ustate ustate; /* in: pstate identifier */
+ __s8 pwrsrc; /* in: target power source */
+ __u8 pad03[5];
+};
+
+
+/*******************************************************************************
+ * DMA FIFO channels
+ ******************************************************************************/
+
+struct nv03_channel_dma_v0 {
+ __u8 version;
+ __u8 chid;
+ __u8 pad02[2];
+ __u32 pushbuf;
+ __u64 offset;
+};
+
+#define G82_CHANNEL_DMA_V0_NTFY_UEVENT 0x00
+
+/*******************************************************************************
+ * GPFIFO channels
+ ******************************************************************************/
+
+struct nv50_channel_gpfifo_v0 {
+ __u8 version;
+ __u8 chid;
+ __u8 pad01[6];
+ __u32 pushbuf;
+ __u32 ilength;
+ __u64 ioffset;
+};
+
+struct kepler_channel_gpfifo_a_v0 {
+ __u8 version;
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR 0x01
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_MSPDEC 0x02
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_MSPPP 0x04
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_MSVLD 0x08
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE0 0x10
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE1 0x20
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_ENC 0x40
+ __u8 engine;
+ __u16 chid;
+ __u8 pad04[4];
+ __u32 pushbuf;
+ __u32 ilength;
+ __u64 ioffset;
+};
+
+#define CHANNEL_GPFIFO_ERROR_NOTIFIER_EEVENT 0x01
+
+/*******************************************************************************
+ * legacy display
+ ******************************************************************************/
+
+#define NV04_DISP_NTFY_VBLANK 0x00
+#define NV04_DISP_NTFY_CONN 0x01
+
+struct nv04_disp_mthd_v0 {
+ __u8 version;
+#define NV04_DISP_SCANOUTPOS 0x00
+ __u8 method;
+ __u8 head;
+ __u8 pad03[5];
+};
+
+struct nv04_disp_scanoutpos_v0 {
+ __u8 version;
+ __u8 pad01[7];
+ __s64 time[2];
+ __u16 vblanks;
+ __u16 vblanke;
+ __u16 vtotal;
+ __u16 vline;
+ __u16 hblanks;
+ __u16 hblanke;
+ __u16 htotal;
+ __u16 hline;
+};
+
+/*******************************************************************************
+ * display
+ ******************************************************************************/
+
+#define NV50_DISP_MTHD 0x00
+
+struct nv50_disp_mthd_v0 {
+ __u8 version;
+#define NV50_DISP_SCANOUTPOS 0x00
+ __u8 method;
+ __u8 head;
+ __u8 pad03[5];
+};
+
+struct nv50_disp_mthd_v1 {
+ __u8 version;
+#define NV50_DISP_MTHD_V1_DAC_PWR 0x10
+#define NV50_DISP_MTHD_V1_DAC_LOAD 0x11
+#define NV50_DISP_MTHD_V1_SOR_PWR 0x20
+#define NV50_DISP_MTHD_V1_SOR_HDA_ELD 0x21
+#define NV50_DISP_MTHD_V1_SOR_HDMI_PWR 0x22
+#define NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT 0x23
+#define NV50_DISP_MTHD_V1_SOR_DP_PWR 0x24
+#define NV50_DISP_MTHD_V1_PIOR_PWR 0x30
+ __u8 method;
+ __u16 hasht;
+ __u16 hashm;
+ __u8 pad06[2];
+};
+
+struct nv50_disp_dac_pwr_v0 {
+ __u8 version;
+ __u8 state;
+ __u8 data;
+ __u8 vsync;
+ __u8 hsync;
+ __u8 pad05[3];
+};
+
+struct nv50_disp_dac_load_v0 {
+ __u8 version;
+ __u8 load;
+ __u8 pad02[2];
+ __u32 data;
+};
+
+struct nv50_disp_sor_pwr_v0 {
+ __u8 version;
+ __u8 state;
+ __u8 pad02[6];
+};
+
+struct nv50_disp_sor_hda_eld_v0 {
+ __u8 version;
+ __u8 pad01[7];
+ __u8 data[];
+};
+
+struct nv50_disp_sor_hdmi_pwr_v0 {
+ __u8 version;
+ __u8 state;
+ __u8 max_ac_packet;
+ __u8 rekey;
+ __u8 pad04[4];
+};
+
+struct nv50_disp_sor_lvds_script_v0 {
+ __u8 version;
+ __u8 pad01[1];
+ __u16 script;
+ __u8 pad04[4];
+};
+
+struct nv50_disp_sor_dp_pwr_v0 {
+ __u8 version;
+ __u8 state;
+ __u8 pad02[6];
+};
+
+struct nv50_disp_pior_pwr_v0 {
+ __u8 version;
+ __u8 state;
+ __u8 type;
+ __u8 pad03[5];
+};
+
+/* core */
+struct nv50_disp_core_channel_dma_v0 {
+ __u8 version;
+ __u8 pad01[3];
+ __u32 pushbuf;
+};
+
+#define NV50_DISP_CORE_CHANNEL_DMA_V0_NTFY_UEVENT 0x00
+
+/* cursor immediate */
+struct nv50_disp_cursor_v0 {
+ __u8 version;
+ __u8 head;
+ __u8 pad02[6];
+};
+
+#define NV50_DISP_CURSOR_V0_NTFY_UEVENT 0x00
+
+/* base */
+struct nv50_disp_base_channel_dma_v0 {
+ __u8 version;
+ __u8 pad01[2];
+ __u8 head;
+ __u32 pushbuf;
+};
+
+#define NV50_DISP_BASE_CHANNEL_DMA_V0_NTFY_UEVENT 0x00
+
+/* overlay */
+struct nv50_disp_overlay_channel_dma_v0 {
+ __u8 version;
+ __u8 pad01[2];
+ __u8 head;
+ __u32 pushbuf;
+};
+
+#define NV50_DISP_OVERLAY_CHANNEL_DMA_V0_NTFY_UEVENT 0x00
+
+/* overlay immediate */
+struct nv50_disp_overlay_v0 {
+ __u8 version;
+ __u8 head;
+ __u8 pad02[6];
+};
+
+#define NV50_DISP_OVERLAY_V0_NTFY_UEVENT 0x00
+
+/*******************************************************************************
+ * fermi
+ ******************************************************************************/
+
+#define FERMI_A_ZBC_COLOR 0x00
+#define FERMI_A_ZBC_DEPTH 0x01
+#define FERMI_A_ZCULL_BIND 0x02
+#define FERMI_A_ZBC_QUERY_COLOR 0x03
+#define FERMI_A_ZBC_QUERY_DEPTH 0x04
+#define FERMI_A_ZBC_QUERY_TABLE_SIZE 0x05
+
+struct fermi_a_zbc_color_v0 {
+ __u8 version;
+#define FERMI_A_ZBC_COLOR_V0_FMT_ZERO 0x01
+#define FERMI_A_ZBC_COLOR_V0_FMT_UNORM_ONE 0x02
+#define FERMI_A_ZBC_COLOR_V0_FMT_RF32_GF32_BF32_AF32 0x04
+#define FERMI_A_ZBC_COLOR_V0_FMT_R16_G16_B16_A16 0x08
+#define FERMI_A_ZBC_COLOR_V0_FMT_RN16_GN16_BN16_AN16 0x0c
+#define FERMI_A_ZBC_COLOR_V0_FMT_RS16_GS16_BS16_AS16 0x10
+#define FERMI_A_ZBC_COLOR_V0_FMT_RU16_GU16_BU16_AU16 0x14
+#define FERMI_A_ZBC_COLOR_V0_FMT_RF16_GF16_BF16_AF16 0x16
+#define FERMI_A_ZBC_COLOR_V0_FMT_A8R8G8B8 0x18
+#define FERMI_A_ZBC_COLOR_V0_FMT_A8RL8GL8BL8 0x1c
+#define FERMI_A_ZBC_COLOR_V0_FMT_A2B10G10R10 0x20
+#define FERMI_A_ZBC_COLOR_V0_FMT_AU2BU10GU10RU10 0x24
+#define FERMI_A_ZBC_COLOR_V0_FMT_A8B8G8R8 0x28
+#define FERMI_A_ZBC_COLOR_V0_FMT_A8BL8GL8RL8 0x2c
+#define FERMI_A_ZBC_COLOR_V0_FMT_AN8BN8GN8RN8 0x30
+#define FERMI_A_ZBC_COLOR_V0_FMT_AS8BS8GS8RS8 0x34
+#define FERMI_A_ZBC_COLOR_V0_FMT_AU8BU8GU8RU8 0x38
+#define FERMI_A_ZBC_COLOR_V0_FMT_A2R10G10B10 0x3c
+#define FERMI_A_ZBC_COLOR_V0_FMT_BF10GF11RF11 0x40
+ __u8 format;
+ __u8 index;
+ __u8 pad03[5];
+ __u32 ds[4];
+ __u32 l2[4];
+};
+
+struct fermi_a_zbc_query_v0 {
+ __u8 version;
+ __u8 pad03[3];
+ __u32 ds[4];
+ __u32 l2[4];
+ __u32 format;
+ __u32 index;
+ __u32 table_size;
+};
+
+struct fermi_a_zbc_depth_v0 {
+ __u8 version;
+#define FERMI_A_ZBC_DEPTH_V0_FMT_FP32 0x01
+ __u8 format;
+ __u8 index;
+ __u8 pad03[5];
+ __u32 ds;
+ __u32 l2;
+};
+
+struct fermi_a_zcull_bind_v0 {
+ __u8 version;
+ __u8 pad03[3];
+#define FERMI_A_ZCULL_BIND_MODE_GLOBAL 0x00
+#define FERMI_A_ZCULL_BIND_MODE_NO_CTXSW 0x01
+#define FERMI_A_ZCULL_BIND_MODE_SEPARATE_BUFFER 0x02
+ __u32 mode;
+ __u64 gpu_va;
+};
+
+#define KEPLER_SET_CHANNEL_PRIORITY 0x00
+#define KEPLER_SET_CHANNEL_TIMEOUT 0x01
+
+struct kepler_set_channel_priority_v0 {
+ __u8 version;
+#define KEPLER_SET_CHANNEL_PRIORITY_LOW 0x00
+#define KEPLER_SET_CHANNEL_PRIORITY_MEDIUM 0x01
+#define KEPLER_SET_CHANNEL_PRIORITY_HIGH 0x02
+ __u8 priority;
+ __u8 pad03[6];
+};
+
+struct kepler_set_channel_timeout_v0 {
+ __u8 version;
+ __u8 pad03[3];
+ __u32 timeout_ms;
+};
+
+#endif
diff --git a/include/drm/nouveau_drm.h b/include/drm/nouveau_drm.h
index e418f9f..1372f53 100644
--- a/include/drm/nouveau_drm.h
+++ b/include/drm/nouveau_drm.h
@@ -27,6 +27,14 @@
#define NOUVEAU_DRM_HEADER_PATCHLEVEL 16
+/* reserved object handles when using deprecated object APIs - these
+ * are here so that libdrm can allow interoperability with the new
+ * object APIs
+ */
+#define NOUVEAU_ABI16_CLIENT 0xffffffff
+#define NOUVEAU_ABI16_DEVICE 0xdddddddd
+#define NOUVEAU_ABI16_CHAN(n) (0xcccc0000 | (n))
+
struct drm_nouveau_channel_alloc {
uint32_t fb_ctxdma_handle;
uint32_t tt_ctxdma_handle;
@@ -114,6 +122,12 @@
uint32_t tile_flags;
};
+struct drm_nouveau_gem_set_tiling {
+ uint32_t handle;
+ uint32_t tile_mode;
+ uint32_t tile_flags;
+};
+
struct drm_nouveau_gem_new {
struct drm_nouveau_gem_info info;
uint32_t channel_hint;
@@ -172,6 +186,21 @@
uint64_t gart_available;
};
+#define NOUVEAU_GEM_PUSHBUF_2_FENCE_WAIT 0x00000001
+#define NOUVEAU_GEM_PUSHBUF_2_FENCE_EMIT 0x00000002
+struct drm_nouveau_gem_pushbuf_2 {
+ uint32_t channel;
+ uint32_t flags;
+ uint32_t nr_push;
+ uint32_t nr_buffers;
+ int32_t fence; /* in/out, depends on flags */
+ uint32_t pad;
+ uint64_t push; /* in raw hw format */
+ uint64_t buffers; /* ptr to drm_nouveau_gem_pushbuf_bo */
+ uint64_t vram_available;
+ uint64_t gart_available;
+};
+
#define NOUVEAU_GEM_CPU_PREP_NOWAIT 0x00000001
#define NOUVEAU_GEM_CPU_PREP_NOBLOCK 0x00000002
#define NOUVEAU_GEM_CPU_PREP_WRITE 0x00000004
@@ -184,6 +213,19 @@
uint32_t handle;
};
+#define NOUVEAU_GEM_AS_SPARSE 0x00000001
+struct drm_nouveau_gem_as_alloc {
+ uint64_t pages; /* in, page length */
+ uint32_t page_size; /* in, byte page size */
+ uint32_t flags; /* in, flags of address space */
+ uint64_t align; /* in, requested alignment in bytes */
+ uint64_t address; /* in/out, non-zero for fixed address allocation */
+};
+
+struct drm_nouveau_gem_as_free {
+ uint64_t address; /* in, byte address */
+};
+
enum nouveau_bus_type {
NV_AGP = 0,
NV_PCI = 1,
@@ -193,6 +235,34 @@
struct drm_nouveau_sarea {
};
+#define NOUVEAU_GEM_CHANNEL_FIFO_ERROR_IDLE_TIMEOUT 8
+#define NOUVEAU_GEM_CHANNEL_GR_ERROR_SW_NOTIFY 13
+#define NOUVEAU_GEM_CHANNEL_FIFO_ERROR_MMU_ERR_FLT 31
+#define NOUVEAU_GEM_CHANNEL_PBDMA_ERROR 32
+struct drm_nouveau_gem_set_error_notifier {
+ uint32_t channel;
+ uint32_t buffer;
+ uint32_t offset; /* in bytes, u32-aligned */
+};
+
+struct drm_nouveau_gem_map {
+ uint32_t handle;
+ uint32_t domain;
+ uint64_t offset;
+ uint64_t delta;
+ uint64_t length;
+ uint32_t tile_mode;
+ uint32_t tile_flags;
+};
+
+struct drm_nouveau_gem_unmap {
+ uint32_t handle;
+ uint32_t pad;
+ uint64_t offset;
+ uint64_t delta;
+ uint64_t length;
+};
+
#define DRM_NOUVEAU_GETPARAM 0x00
#define DRM_NOUVEAU_SETPARAM 0x01
#define DRM_NOUVEAU_CHANNEL_ALLOC 0x02
@@ -207,4 +277,14 @@
#define DRM_NOUVEAU_GEM_CPU_FINI 0x43
#define DRM_NOUVEAU_GEM_INFO 0x44
+/* The ioctls below are marked as staging */
+#define DRM_NOUVEAU_GEM_SET_TILING 0x50
+#define DRM_NOUVEAU_GEM_PUSHBUF_2 0x51
+#define DRM_NOUVEAU_GEM_SET_INFO 0x52
+#define DRM_NOUVEAU_GEM_AS_ALLOC 0x53
+#define DRM_NOUVEAU_GEM_AS_FREE 0x54
+#define DRM_NOUVEAU_GEM_SET_ERROR_NOTIFIER 0x55
+#define DRM_NOUVEAU_GEM_MAP 0x56
+#define DRM_NOUVEAU_GEM_UNMAP 0x57
+
#endif /* __NOUVEAU_DRM_H__ */
diff --git a/include/drm/nouveau_ioctl.h b/include/drm/nouveau_ioctl.h
new file mode 100644
index 0000000..4cd8e32
--- /dev/null
+++ b/include/drm/nouveau_ioctl.h
@@ -0,0 +1,128 @@
+#ifndef __NVIF_IOCTL_H__
+#define __NVIF_IOCTL_H__
+
+struct nvif_ioctl_v0 {
+ __u8 version;
+#define NVIF_IOCTL_V0_OWNER_NVIF 0x00
+#define NVIF_IOCTL_V0_OWNER_ANY 0xff
+ __u8 owner;
+#define NVIF_IOCTL_V0_NOP 0x00
+#define NVIF_IOCTL_V0_SCLASS 0x01
+#define NVIF_IOCTL_V0_NEW 0x02
+#define NVIF_IOCTL_V0_DEL 0x03
+#define NVIF_IOCTL_V0_MTHD 0x04
+#define NVIF_IOCTL_V0_RD 0x05
+#define NVIF_IOCTL_V0_WR 0x06
+#define NVIF_IOCTL_V0_MAP 0x07
+#define NVIF_IOCTL_V0_UNMAP 0x08
+#define NVIF_IOCTL_V0_NTFY_NEW 0x09
+#define NVIF_IOCTL_V0_NTFY_DEL 0x0a
+#define NVIF_IOCTL_V0_NTFY_GET 0x0b
+#define NVIF_IOCTL_V0_NTFY_PUT 0x0c
+ __u8 type;
+ __u8 path_nr;
+#define NVIF_IOCTL_V0_ROUTE_NVIF 0x00
+#define NVIF_IOCTL_V0_ROUTE_HIDDEN 0xff
+ __u8 pad04[3];
+ __u8 route;
+ __u64 token;
+ __u32 path[8]; /* in reverse */
+ __u8 data[]; /* ioctl data (below) */
+};
+
+struct nvif_ioctl_nop {
+};
+
+struct nvif_ioctl_sclass_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 count;
+ __u8 pad02[6];
+ __u32 oclass[];
+};
+
+struct nvif_ioctl_new_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 pad01[6];
+ __u8 route;
+ __u64 token;
+ __u32 handle;
+/* these class numbers are made up by us, and not nvidia-assigned */
+#define NVIF_IOCTL_NEW_V0_PERFCTR 0x0000ffff
+#define NVIF_IOCTL_NEW_V0_CONTROL 0x0000fffe
+ __u32 oclass;
+ __u8 data[]; /* class data (class.h) */
+};
+
+struct nvif_ioctl_del {
+};
+
+struct nvif_ioctl_rd_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 size;
+ __u8 pad02[2];
+ __u32 data;
+ __u64 addr;
+};
+
+struct nvif_ioctl_wr_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 size;
+ __u8 pad02[2];
+ __u32 data;
+ __u64 addr;
+};
+
+struct nvif_ioctl_map_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 pad01[3];
+ __u32 length;
+ __u64 handle;
+};
+
+struct nvif_ioctl_unmap {
+};
+
+struct nvif_ioctl_ntfy_new_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 event;
+ __u8 index;
+ __u8 pad03[5];
+ __u8 data[]; /* event request data (event.h) */
+};
+
+struct nvif_ioctl_ntfy_del_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 index;
+ __u8 pad02[6];
+};
+
+struct nvif_ioctl_ntfy_get_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 index;
+ __u8 pad02[6];
+};
+
+struct nvif_ioctl_ntfy_put_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 index;
+ __u8 pad02[6];
+};
+
+struct nvif_ioctl_mthd_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 method;
+ __u8 pad02[6];
+ __u8 data[]; /* method data (class.h) */
+};
+
+#endif
diff --git a/include/drm/tegra_drm.h b/include/drm/tegra_drm.h
index 7c0fe0e..1be09c4 100644
--- a/include/drm/tegra_drm.h
+++ b/include/drm/tegra_drm.h
@@ -1,29 +1,23 @@
/*
* Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved.
*
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
*
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
*
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _UAPI_TEGRA_DRM_H_
#define _UAPI_TEGRA_DRM_H_
-#include <drm.h>
+#include <drm/drm.h>
#define DRM_TEGRA_GEM_CREATE_TILED (1 << 0)
#define DRM_TEGRA_GEM_CREATE_BOTTOM_UP (1 << 1)
@@ -121,6 +115,7 @@
__u32 num_waitchks;
__u32 waitchk_mask;
__u32 timeout;
+ __u32 pad;
__u64 syncpts;
__u64 cmdbufs;
__u64 relocs;
@@ -168,6 +163,34 @@
__u32 flags;
};
+enum request_type {
+ DRM_TEGRA_REQ_TYPE_CLK_KHZ = 0,
+ DRM_TEGRA_REQ_TYPE_BW_KBPS,
+};
+
+struct drm_tegra_get_clk_rate {
+ /* class ID*/
+ __u32 id;
+ /* request type: KBps or KHz */
+ __u32 type;
+ /* numeric value for type */
+ __u64 data;
+};
+
+struct drm_tegra_set_clk_rate {
+ /* class ID*/
+ __u32 id;
+ /* request type: KBps or KHz */
+ __u32 type;
+ /* numeric value for type */
+ __u64 data;
+};
+
+struct drm_tegra_keepon {
+ /* channel context (from opening a channel) */
+ __u64 context;
+};
+
#define DRM_TEGRA_GEM_CREATE 0x00
#define DRM_TEGRA_GEM_MMAP 0x01
#define DRM_TEGRA_SYNCPT_READ 0x02
@@ -182,6 +205,10 @@
#define DRM_TEGRA_GEM_GET_TILING 0x0b
#define DRM_TEGRA_GEM_SET_FLAGS 0x0c
#define DRM_TEGRA_GEM_GET_FLAGS 0x0d
+#define DRM_TEGRA_GET_CLK_RATE 0x0e
+#define DRM_TEGRA_SET_CLK_RATE 0x0f
+#define DRM_TEGRA_START_KEEPON 0x10
+#define DRM_TEGRA_STOP_KEEPON 0x11
#define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct drm_tegra_gem_create)
#define DRM_IOCTL_TEGRA_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_MMAP, struct drm_tegra_gem_mmap)
@@ -197,5 +224,9 @@
#define DRM_IOCTL_TEGRA_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_TILING, struct drm_tegra_gem_get_tiling)
#define DRM_IOCTL_TEGRA_GEM_SET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_FLAGS, struct drm_tegra_gem_set_flags)
#define DRM_IOCTL_TEGRA_GEM_GET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_FLAGS, struct drm_tegra_gem_get_flags)
+#define DRM_IOCTL_TEGRA_GET_CLK_RATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_CLK_RATE, struct drm_tegra_get_clk_rate)
+#define DRM_IOCTL_TEGRA_SET_CLK_RATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SET_CLK_RATE, struct drm_tegra_set_clk_rate)
+#define DRM_IOCTL_TEGRA_START_KEEPON DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_START_KEEPON, struct drm_tegra_keepon)
+#define DRM_IOCTL_TEGRA_STOP_KEEPON DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_STOP_KEEPON, struct drm_tegra_keepon)
#endif
diff --git a/intel/Android.mk b/intel/Android.mk
index 5407ff3..2a0dc4c 100644
--- a/intel/Android.mk
+++ b/intel/Android.mk
@@ -29,11 +29,10 @@
LOCAL_MODULE := libdrm_intel
-LOCAL_SRC_FILES := $(LIBDRM_INTEL_FILES)
+# Removed dependency to libpciaccess: not used on Android
+LOCAL_SHARED_LIBRARIES := libdrm
-LOCAL_SHARED_LIBRARIES := \
- libdrm \
- libpciaccess
+LOCAL_SRC_FILES := $(LIBDRM_INTEL_FILES)
include $(LIBDRM_COMMON_MK)
include $(BUILD_SHARED_LIBRARY)
diff --git a/intel/intel_bufmgr.c b/intel/intel_bufmgr.c
index a285340..5bad93f 100644
--- a/intel/intel_bufmgr.c
+++ b/intel/intel_bufmgr.c
@@ -36,7 +36,9 @@
#include <errno.h>
#include <drm.h>
#include <i915_drm.h>
+#ifndef __ANDROID__
#include <pciaccess.h>
+#endif
#include "libdrm_macros.h"
#include "intel_bufmgr.h"
#include "intel_bufmgr_priv.h"
@@ -326,6 +328,7 @@
return -1;
}
+#ifndef __ANDROID__
static size_t
drm_intel_probe_agp_aperture_size(int fd)
{
@@ -351,6 +354,15 @@
pci_system_cleanup ();
return size;
}
+#else
+static size_t
+drm_intel_probe_agp_aperture_size(int fd)
+{
+ /* Nothing seems to rely on this value on Android anyway... */
+ fprintf(stderr, "%s: Mappable aperture size hardcoded to 64MiB\n", __func__);
+ return 64 * 1024 * 1024;
+}
+#endif
int
drm_intel_get_aperture_sizes(int fd, size_t *mappable, size_t *total)
diff --git a/libdrm_macros.h b/libdrm_macros.h
index 639d090..b88fdce 100644
--- a/libdrm_macros.h
+++ b/libdrm_macros.h
@@ -46,8 +46,6 @@
#if defined(ANDROID) && !defined(__LP64__)
#include <errno.h> /* for EINVAL */
-extern void *__mmap2(void *, size_t, int, int, int, size_t);
-
static inline void *drm_mmap(void *addr, size_t length, int prot, int flags,
int fd, loff_t offset)
{
@@ -57,7 +55,7 @@
return MAP_FAILED;
}
- return __mmap2(addr, length, prot, flags, fd, (size_t) (offset >> 12));
+ return mmap64(addr, length, prot, flags, fd, offset);
}
# define drm_munmap(addr, length) \
diff --git a/libkms/Android.mk b/libkms/Android.mk
index 0be7205..9f81d8e 100644
--- a/libkms/Android.mk
+++ b/libkms/Android.mk
@@ -2,16 +2,20 @@
intel_drivers := i915 i965 i915g ilo
radeon_drivers := r300g r600g radeonsi
+rockchip_drivers := rockchip
nouveau_drivers := nouveau
virgl_drivers := virgl
vmwgfx_drivers := vmwgfx
+tegra_drivers := tegra
valid_drivers := \
$(intel_drivers) \
$(radeon_drivers) \
+ $(rockchip_drivers) \
$(nouveau_drivers) \
$(virgl_drivers) \
- $(vmwgfx_drivers)
+ $(vmwgfx_drivers) \
+ $(tegra_drivers)
# warn about invalid drivers
invalid_drivers := $(filter-out $(valid_drivers), $(DRM_GPU_DRIVERS))
diff --git a/rockchip/Android.mk b/rockchip/Android.mk
new file mode 100644
index 0000000..05d421e
--- /dev/null
+++ b/rockchip/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libdrm_rockchip
+
+LOCAL_SHARED_LIBRARIES := libdrm
+
+LOCAL_SRC_FILES := rockchip_drm.c
+
+LOCAL_CFLAGS := \
+ -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1
+
+LOCAL_SHARED_LIBRARIES := \
+ libdrm
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/rockchip/Makefile.am b/rockchip/Makefile.am
new file mode 100644
index 0000000..2ebb82f
--- /dev/null
+++ b/rockchip/Makefile.am
@@ -0,0 +1,20 @@
+AM_CFLAGS = \
+ $(WARN_CFLAGS) \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/rockchip \
+ $(PTHREADSTUBS_CFLAGS) \
+ -I$(top_srcdir)/include/drm
+
+libdrm_rockchip_la_LTLIBRARIES = libdrm_rockchip.la
+libdrm_rockchip_ladir = $(libdir)
+libdrm_rockchip_la_LDFLAGS = -version-number 1:0:0 -no-undefined
+libdrm_rockchip_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@
+
+libdrm_rockchip_la_SOURCES = \
+ rockchip_drm.c
+
+libdrm_rockchipincludedir = ${includedir}/libdrm
+libdrm_rockchipinclude_HEADERS = rockchip_drmif.h rockchip_drm.h
+
+pkgconfigdir = @pkgconfigdir@
+pkgconfig_DATA = libdrm_rockchip.pc
diff --git a/rockchip/libdrm_rockchip.pc.in b/rockchip/libdrm_rockchip.pc.in
new file mode 100644
index 0000000..13f22ac
--- /dev/null
+++ b/rockchip/libdrm_rockchip.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libdrm_rockchip
+Description: Userspace interface to rockchip kernel DRM services
+Version: 0.1
+Libs: -L${libdir} -ldrm_rockchip
+Cflags: -I${includedir} -I${includedir}/libdrm
+Requires.private: libdrm
diff --git a/rockchip/rockchip_drm.c b/rockchip/rockchip_drm.c
new file mode 100644
index 0000000..44a78be
--- /dev/null
+++ b/rockchip/rockchip_drm.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) ROCKCHIP, Inc.
+ * Author:yzq<yzq@rock-chips.com>
+ *
+ * based on exynos_drm.c
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/mman.h>
+#include <linux/stddef.h>
+
+#include <xf86drm.h>
+
+#include "rockchip_drm.h"
+#include "rockchip_drmif.h"
+
+/*
+ * Create rockchip drm device object.
+ *
+ * @fd: file descriptor to rockchip drm driver opened.
+ *
+ * if true, return the device object else NULL.
+ */
+struct rockchip_device *rockchip_device_create(int fd)
+{
+ struct rockchip_device *dev;
+
+ dev = calloc(1, sizeof(*dev));
+ if (!dev) {
+ fprintf(stderr, "failed to create device[%s].\n",
+ strerror(errno));
+ return NULL;
+ }
+
+ dev->fd = fd;
+
+ return dev;
+}
+
+/*
+ * Destroy rockchip drm device object
+ *
+ * @dev: rockchip drm device object.
+ */
+void rockchip_device_destroy(struct rockchip_device *dev)
+{
+ free(dev);
+}
+
+/*
+ * Create a rockchip buffer object to rockchip drm device.
+ *
+ * @dev: rockchip drm device object.
+ * @size: user-desired size.
+ * flags: user-desired memory type.
+ * user can set one or more types among several types to memory
+ * allocation and cache attribute types. and as default,
+ * ROCKCHIP_BO_NONCONTIG and ROCKCHIP-BO_NONCACHABLE types would
+ * be used.
+ *
+ * if true, return a rockchip buffer object else NULL.
+ */
+struct rockchip_bo *rockchip_bo_create(struct rockchip_device *dev,
+ size_t size, uint32_t flags)
+{
+ struct rockchip_bo *bo;
+ struct drm_rockchip_gem_create req = {
+ .size = size,
+ .flags = flags,
+ };
+
+ if (size == 0) {
+ fprintf(stderr, "invalid size.\n");
+ return NULL;
+ }
+
+ bo = calloc(1, sizeof(*bo));
+ if (!bo) {
+ fprintf(stderr, "failed to create bo[%s].\n",
+ strerror(errno));
+ goto fail;
+ }
+
+ bo->dev = dev;
+
+ if (drmIoctl(dev->fd, DRM_IOCTL_ROCKCHIP_GEM_CREATE, &req)){
+ fprintf(stderr, "failed to create gem object[%s].\n",
+ strerror(errno));
+ goto err_free_bo;
+ }
+
+ bo->handle = req.handle;
+ bo->size = size;
+ bo->flags = flags;
+
+ return bo;
+
+err_free_bo:
+ free(bo);
+fail:
+ return NULL;
+}
+
+struct rockchip_bo *rockchip_bo_from_handle(struct rockchip_device *dev,
+ uint32_t handle, uint32_t flags, uint32_t size)
+{
+ struct rockchip_bo *bo;
+
+ if (size == 0) {
+ fprintf(stderr, "invalid size.\n");
+ return NULL;
+ }
+
+ bo = calloc(1, sizeof(*bo));
+ if (!bo) {
+ fprintf(stderr, "failed to create bo[%s].\n",
+ strerror(errno));
+ return NULL;
+ }
+
+ bo->dev = dev;
+ bo->handle = handle;
+ bo->size = size;
+ bo->flags = flags;
+
+ return bo;
+}
+
+/*
+ * Destroy a rockchip buffer object.
+ *
+ * @bo: a rockchip buffer object to be destroyed.
+ */
+void rockchip_bo_destroy(struct rockchip_bo *bo)
+{
+ if (!bo)
+ return;
+
+ if (bo->vaddr)
+ munmap(bo->vaddr, bo->size);
+
+ if (bo->handle) {
+ struct drm_gem_close req = {
+ .handle = bo->handle,
+ };
+
+ drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
+ }
+
+ free(bo);
+}
+
+
+/*
+ * Get a rockchip buffer object from a gem global object name.
+ *
+ * @dev: a rockchip device object.
+ * @name: a gem global object name exported by another process.
+ *
+ * this interface is used to get a rockchip buffer object from a gem
+ * global object name sent by another process for buffer sharing.
+ *
+ * if true, return a rockchip buffer object else NULL.
+ *
+ */
+struct rockchip_bo *rockchip_bo_from_name(struct rockchip_device *dev,
+ uint32_t name)
+{
+ struct rockchip_bo *bo;
+ struct drm_gem_open req = {
+ .name = name,
+ };
+
+ bo = calloc(1, sizeof(*bo));
+ if (!bo) {
+ fprintf(stderr, "failed to allocate bo[%s].\n",
+ strerror(errno));
+ return NULL;
+ }
+
+ if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) {
+ fprintf(stderr, "failed to open gem object[%s].\n",
+ strerror(errno));
+ goto err_free_bo;
+ }
+
+ bo->dev = dev;
+ bo->name = name;
+ bo->handle = req.handle;
+
+ return bo;
+
+err_free_bo:
+ free(bo);
+ return NULL;
+}
+
+/*
+ * Get a gem global object name from a gem object handle.
+ *
+ * @bo: a rockchip buffer object including gem handle.
+ * @name: a gem global object name to be got by kernel driver.
+ *
+ * this interface is used to get a gem global object name from a gem object
+ * handle to a buffer that wants to share it with another process.
+ *
+ * if true, return 0 else negative.
+ */
+int rockchip_bo_get_name(struct rockchip_bo *bo, uint32_t *name)
+{
+ if (!bo->name) {
+ struct drm_gem_flink req = {
+ .handle = bo->handle,
+ };
+ int ret;
+
+ ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req);
+ if (ret) {
+ fprintf(stderr, "failed to get gem global name[%s].\n",
+ strerror(errno));
+ return ret;
+ }
+
+ bo->name = req.name;
+ }
+
+ *name = bo->name;
+
+ return 0;
+}
+
+uint32_t rockchip_bo_handle(struct rockchip_bo *bo)
+{
+ return bo->handle;
+}
+
+/*
+ * Mmap a buffer to user space.
+ *
+ * @bo: a rockchip buffer object including a gem object handle to be mmapped
+ * to user space.
+ *
+ * if true, user pointer mmaped else NULL.
+ */
+void *rockchip_bo_map(struct rockchip_bo *bo)
+{
+ if (!bo->vaddr) {
+ struct rockchip_device *dev = bo->dev;
+ struct drm_rockchip_gem_map_off req = {
+ .handle = bo->handle,
+ };
+ int ret;
+
+ ret = drmIoctl(dev->fd, DRM_IOCTL_ROCKCHIP_GEM_MAP_OFFSET, &req);
+ if (ret) {
+ fprintf(stderr, "failed to ioctl gem map offset[%s].\n",
+ strerror(errno));
+ return NULL;
+ }
+
+ bo->vaddr = mmap(0, bo->size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, dev->fd, req.offset);
+ if (bo->vaddr == MAP_FAILED) {
+ fprintf(stderr, "failed to mmap buffer[%s].\n",
+ strerror(errno));
+ return NULL;
+ }
+ }
+
+ return bo->vaddr;
+}
diff --git a/rockchip/rockchip_drm.h b/rockchip/rockchip_drm.h
new file mode 100644
index 0000000..13977d5
--- /dev/null
+++ b/rockchip/rockchip_drm.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) Fuzhou Rockchip Electronics Co.Ltd
+ * Authors:
+ * Mark Yao <yzq@rock-chips.com>
+ *
+ * based on exynos_drm.h
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _ROCKCHIP_DRM_H_
+#define _ROCKCHIP_DRM_H_
+
+#include <stdint.h>
+#include "drm.h"
+
+/**
+ * User-desired buffer creation information structure.
+ *
+ * @size: user-desired memory allocation size.
+ * - this size value would be page-aligned internally.
+ * @flags: user request for setting memory type or cache attributes.
+ * @handle: returned a handle to created gem object.
+ * - this handle will be set by gem module of kernel side.
+ */
+struct drm_rockchip_gem_create {
+ uint64_t size;
+ uint32_t flags;
+ uint32_t handle;
+};
+
+/**
+ * A structure for getting buffer offset.
+ *
+ * @handle: a pointer to gem object created.
+ * @pad: just padding to be 64-bit aligned.
+ * @offset: relatived offset value of the memory region allocated.
+ * - this value should be set by user.
+ */
+struct drm_rockchip_gem_map_off {
+ uint32_t handle;
+ uint32_t pad;
+ uint64_t offset;
+};
+
+#define DRM_ROCKCHIP_GEM_CREATE 0x00
+#define DRM_ROCKCHIP_GEM_MAP_OFFSET 0x01
+
+#define DRM_IOCTL_ROCKCHIP_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + \
+ DRM_ROCKCHIP_GEM_CREATE, struct drm_rockchip_gem_create)
+
+#define DRM_IOCTL_ROCKCHIP_GEM_MAP_OFFSET DRM_IOWR(DRM_COMMAND_BASE + \
+ DRM_ROCKCHIP_GEM_MAP_OFFSET, struct drm_rockchip_gem_map_off)
+
+#endif
diff --git a/rockchip/rockchip_drmif.h b/rockchip/rockchip_drmif.h
new file mode 100644
index 0000000..5c549a0
--- /dev/null
+++ b/rockchip/rockchip_drmif.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) ROCKCHIP, Inc.
+ * Author:yzq<yzq@rock-chips.com>
+ *
+ * based on exynos_drmif.h
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef ROCKCHIP_DRMIF_H_
+#define ROCKCHIP_DRMIF_H_
+
+#include <xf86drm.h>
+#include <stdint.h>
+#include "rockchip_drm.h"
+
+struct rockchip_device {
+ int fd;
+};
+
+/*
+ * Rockchip Buffer Object structure.
+ *
+ * @dev: rockchip device object allocated.
+ * @handle: a gem handle to gem object created.
+ * @flags: indicate memory allocation and cache attribute types.
+ * @size: size to the buffer created.
+ * @vaddr: user space address to a gem buffer mmaped.
+ * @name: a gem global handle from flink request.
+ */
+struct rockchip_bo {
+ struct rockchip_device *dev;
+ uint32_t handle;
+ uint32_t flags;
+ size_t size;
+ void *vaddr;
+ uint32_t name;
+};
+
+/*
+ * device related functions:
+ */
+struct rockchip_device *rockchip_device_create(int fd);
+void rockchip_device_destroy(struct rockchip_device *dev);
+
+/*
+ * buffer-object related functions:
+ */
+struct rockchip_bo *rockchip_bo_create(struct rockchip_device *dev,
+ size_t size, uint32_t flags);
+int rockchip_bo_get_info(struct rockchip_device *dev, uint32_t handle,
+ size_t *size, uint32_t *flags);
+void rockchip_bo_destroy(struct rockchip_bo *bo);
+struct rockchip_bo *rockchip_bo_from_name(struct rockchip_device *dev,
+ uint32_t name);
+int rockchip_bo_get_name(struct rockchip_bo *bo, uint32_t *name);
+uint32_t rockchip_bo_handle(struct rockchip_bo *bo);
+struct rockchip_bo *rockchip_bo_from_handle(struct rockchip_device *dev,
+ uint32_t handle, uint32_t flags, uint32_t size);
+void *rockchip_bo_map(struct rockchip_bo *bo);
+#endif /* ROCKCHIP_DRMIF_H_ */
diff --git a/tegra/Android.mk b/tegra/Android.mk
new file mode 100644
index 0000000..d2a1a59
--- /dev/null
+++ b/tegra/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libdrm_tegra
+
+LOCAL_SHARED_LIBRARIES := libdrm
+
+LOCAL_SRC_FILES := tegra.c
+
+LOCAL_CFLAGS := \
+ -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1
+
+LOCAL_SHARED_LIBRARIES := \
+ libdrm
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/tegra/private.h b/tegra/private.h
index bb6c1a5..571caa5 100644
--- a/tegra/private.h
+++ b/tegra/private.h
@@ -41,9 +41,10 @@
struct drm_tegra_bo {
struct drm_tegra *drm;
uint32_t handle;
- uint32_t offset;
+ uint64_t offset;
uint32_t flags;
uint32_t size;
+ uint32_t name;
atomic_t ref;
void *map;
};
diff --git a/tegra/tegra.c b/tegra/tegra.c
index f7dc89a..66f19e9 100644
--- a/tegra/tegra.c
+++ b/tegra/tegra.c
@@ -166,6 +166,61 @@
return 0;
}
+int drm_tegra_bo_name_ref(struct drm_tegra *drm, uint32_t name, uint32_t size,
+ struct drm_tegra_bo **bop)
+{
+ struct drm_tegra_bo *bo;
+ struct drm_gem_open open_args;
+ struct drm_gem_close close_args;
+ int ret;
+
+ memset(&open_args, 0, sizeof(open_args));
+
+ open_args.name = name;
+
+ ret = drmIoctl(drm->fd, DRM_IOCTL_GEM_OPEN, &open_args);
+ if (ret)
+ return ret;
+
+ ret = drm_tegra_bo_wrap(bop, drm, open_args.handle, 0, size);
+ if (ret)
+ goto err;
+
+ (*bop)->name = name;
+
+ return 0;
+
+err:
+ memset(&close_args, 0, sizeof(close_args));
+ close_args.handle = open_args.handle;
+ drmIoctl(drm->fd, DRM_IOCTL_GEM_CLOSE, &close_args);
+
+ return ret;
+}
+
+int drm_tegra_bo_name_get(struct drm_tegra_bo *bo, uint32_t *name)
+{
+ struct drm_gem_flink args;
+ int ret;
+
+ args.handle = bo->handle;
+
+ *name = bo->name;
+ if (*name && *name != ~0U)
+ return 0;
+
+ ret = drmIoctl(bo->drm->fd, DRM_IOCTL_GEM_FLINK, &args);
+ if (ret) {
+ *name = 0;
+ return ret;
+ }
+
+ bo->name = args.name;
+ *name = bo->name;
+
+ return 0;
+}
+
struct drm_tegra_bo *drm_tegra_bo_ref(struct drm_tegra_bo *bo)
{
if (bo)
diff --git a/tegra/tegra.h b/tegra/tegra.h
index 31b0995..e10eab7 100644
--- a/tegra/tegra.h
+++ b/tegra/tegra.h
@@ -38,6 +38,11 @@
uint32_t flags, uint32_t size);
int drm_tegra_bo_wrap(struct drm_tegra_bo **bop, struct drm_tegra *drm,
uint32_t handle, uint32_t flags, uint32_t size);
+
+int drm_tegra_bo_name_ref(struct drm_tegra *drm, uint32_t name, uint32_t size,
+ struct drm_tegra_bo **bop);
+int drm_tegra_bo_name_get(struct drm_tegra_bo *bo, uint32_t *name);
+
struct drm_tegra_bo *drm_tegra_bo_ref(struct drm_tegra_bo *bo);
void drm_tegra_bo_unref(struct drm_tegra_bo *bo);
int drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 0355a92..f2bb4d4 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,7 +1,7 @@
SUBDIRS = util kms modeprint proptest modetest vbltest
if HAVE_LIBKMS
-SUBDIRS += kmstest
+SUBDIRS += kmstest planetest
endif
if HAVE_RADEON
diff --git a/tests/modetest/Android.mk b/tests/modetest/Android.mk
index c1a71fd..ab40b80 100644
--- a/tests/modetest/Android.mk
+++ b/tests/modetest/Android.mk
@@ -3,12 +3,14 @@
include $(CLEAR_VARS)
include $(LOCAL_PATH)/Makefile.sources
-LOCAL_SRC_FILES := $(MODETEST_FILES)
+LOCAL_SRC_FILES := $(filter-out %.h,$(MODETEST_FILES))
LOCAL_MODULE := modetest
LOCAL_SHARED_LIBRARIES := libdrm
LOCAL_STATIC_LIBRARIES := libdrm_util
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/..
+
include $(LIBDRM_COMMON_MK)
include $(BUILD_EXECUTABLE)
diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index c390d87..cd91119 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -524,6 +524,7 @@
return NULL;
drmSetClientCap(dev->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
+ drmSetClientCap(dev->fd, DRM_CLIENT_CAP_ATOMIC, 1);
res->res = drmModeGetResources(dev->fd);
if (!res->res) {
diff --git a/tests/planetest/Android.mk b/tests/planetest/Android.mk
new file mode 100644
index 0000000..3616e2b
--- /dev/null
+++ b/tests/planetest/Android.mk
@@ -0,0 +1,23 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/Makefile.sources
+
+LOCAL_SRC_FILES := $(filter-out %.h,$(PLANETEST_COMMON_FILES) $(PLANETEST_FILES))
+
+LOCAL_MODULE := planetest
+
+LOCAL_SHARED_LIBRARIES := libdrm
+
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/Makefile.sources
+
+LOCAL_SRC_FILES := $(filter-out %.h,$(PLANETEST_COMMON_FILES) $(ATOMICTEST_FILES))
+
+LOCAL_MODULE := atomictest
+
+LOCAL_SHARED_LIBRARIES := libdrm
+
+include $(BUILD_EXECUTABLE)
diff --git a/tests/planetest/Makefile.am b/tests/planetest/Makefile.am
new file mode 100644
index 0000000..b82d05b
--- /dev/null
+++ b/tests/planetest/Makefile.am
@@ -0,0 +1,30 @@
+include Makefile.sources
+
+AM_CFLAGS = $(filter-out -Wpointer-arith, $(WARN_CFLAGS))
+
+AM_CFLAGS += \
+ -I$(top_srcdir)/include/drm \
+ -I$(top_srcdir)/libkms/ \
+ -I$(top_srcdir)
+
+PLANETEST_COMMON_LDADD = \
+ $(top_builddir)/libdrm.la \
+ $(top_builddir)/libkms/libkms.la \
+ -lpthread
+
+if HAVE_INSTALL_TESTS
+bin_PROGRAMS = \
+ atomictest \
+ planetest
+else
+noinst_PROGRAMS = \
+ atomictest \
+ planetest
+endif
+
+atomictest_CFLAGS=-DUSE_ATOMIC_API ${AM_CFLAGS}
+atomictest_SOURCES=${PLANETEST_COMMON_FILES} ${ATOMICTEST_FILES}
+planetest_SOURCES=${PLANETEST_COMMON_FILES} ${PLANETEST_FILES}
+
+atomictest_LDADD=${PLANETEST_COMMON_LDADD}
+planetest_LDADD=${PLANETEST_COMMON_LDADD}
diff --git a/tests/planetest/Makefile.sources b/tests/planetest/Makefile.sources
new file mode 100644
index 0000000..3cbeb2b
--- /dev/null
+++ b/tests/planetest/Makefile.sources
@@ -0,0 +1,13 @@
+PLANETEST_COMMON_FILES := \
+ bo.c \
+ bo.h \
+ dev.c \
+ dev.h \
+ modeset.c \
+ modeset.h
+
+ATOMICTEST_FILES := \
+ atomictest.c
+
+PLANETEST_FILES := \
+ planetest.c
diff --git a/tests/planetest/atomictest.c b/tests/planetest/atomictest.c
new file mode 100644
index 0000000..5fec911
--- /dev/null
+++ b/tests/planetest/atomictest.c
@@ -0,0 +1,151 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/select.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <time.h>
+#include <errno.h>
+
+#include <xf86drm.h>
+
+#include "dev.h"
+#include "bo.h"
+#include "modeset.h"
+
+static int terminate = 0;
+
+static void sigint_handler(int arg)
+{
+ terminate = 1;
+}
+
+static void
+page_flip_handler(int fd, unsigned int sequence, unsigned int tv_sec,
+ unsigned int tv_usec, void *user_data)
+{
+}
+
+static void incrementor(int *inc, int *val, int increment, int lower, int upper)
+{
+ if(*inc > 0)
+ *inc = *val + increment >= upper ? -1 : 1;
+ else
+ *inc = *val - increment <= lower ? 1 : -1;
+ *val += *inc * increment;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret, i, j, num_test_planes;
+ int x_inc = 1, x = 0, y_inc = 1, y = 0;
+ uint32_t plane_w = 128, plane_h = 128;
+ struct sp_dev *dev;
+ struct sp_plane **plane = NULL;
+ struct sp_crtc *test_crtc;
+ fd_set fds;
+ drmModePropertySetPtr pset;
+ drmEventContext event_context = {
+ .version = DRM_EVENT_CONTEXT_VERSION,
+ .page_flip_handler = page_flip_handler,
+ };
+ int card = 0, crtc = 0;
+
+ signal(SIGINT, sigint_handler);
+
+ parse_arguments(argc, argv, &card, &crtc);
+
+ dev = create_sp_dev(card);
+ if (!dev) {
+ printf("Failed to create sp_dev\n");
+ return -1;
+ }
+
+ if (crtc >= dev->num_crtcs) {
+ printf("Invalid crtc %d (num=%d)\n", crtc, dev->num_crtcs);
+ return -1;
+ }
+
+ ret = initialize_screens(dev);
+ if (ret) {
+ printf("Failed to initialize screens\n");
+ goto out;
+ }
+ test_crtc = &dev->crtcs[crtc];
+
+ plane = calloc(dev->num_planes, sizeof(*plane));
+ if (!plane) {
+ printf("Failed to allocate plane array\n");
+ goto out;
+ }
+
+ /* Create our planes */
+ num_test_planes = test_crtc->num_planes;
+ for (i = 0; i < num_test_planes; i++) {
+ plane[i] = get_sp_plane(dev, test_crtc);
+ if (!plane[i]) {
+ printf("no unused planes available\n");
+ goto out;
+ }
+
+ plane[i]->bo = create_sp_bo(dev, plane_w, plane_h, 16, plane[i]->format, 0);
+ if (!plane[i]->bo) {
+ printf("failed to create plane bo\n");
+ goto out;
+ }
+
+ fill_bo(plane[i]->bo, 0xFF, 0xFF, 0xFF, 0xFF);
+ }
+
+ pset = drmModePropertySetAlloc();
+ if (!pset) {
+ printf("Failed to allocate the property set\n");
+ goto out;
+ }
+
+ while (!terminate) {
+ FD_ZERO(&fds);
+ FD_SET(dev->fd, &fds);
+
+ incrementor(&x_inc, &x, 5, 0,
+ test_crtc->crtc->mode.hdisplay - plane_w);
+ incrementor(&y_inc, &y, 5, 0, test_crtc->crtc->mode.vdisplay -
+ plane_h * num_test_planes);
+
+ for (j = 0; j < num_test_planes; j++) {
+ ret = set_sp_plane_pset(dev, plane[j], pset, test_crtc,
+ x, y + j * plane_h);
+ if (ret) {
+ printf("failed to move plane %d\n", ret);
+ goto out;
+ }
+ }
+
+ ret = drmModePropertySetCommit(dev->fd,
+ DRM_MODE_PAGE_FLIP_EVENT, NULL, pset);
+ if (ret) {
+ printf("failed to commit properties ret=%d\n", ret);
+ goto out;
+ }
+
+ do {
+ ret = select(dev->fd + 1, &fds, NULL, NULL, NULL);
+ } while (ret == -1 && errno == EINTR);
+
+ if (FD_ISSET(dev->fd, &fds))
+ drmHandleEvent(dev->fd, &event_context);
+ }
+
+ drmModePropertySetFree(pset);
+
+ for (i = 0; i < num_test_planes; i++)
+ put_sp_plane(plane[i]);
+
+out:
+ destroy_sp_dev(dev);
+ free(plane);
+ return ret;
+}
diff --git a/tests/planetest/bo.c b/tests/planetest/bo.c
new file mode 100644
index 0000000..d4b82c6
--- /dev/null
+++ b/tests/planetest/bo.c
@@ -0,0 +1,234 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+#include <drm_fourcc.h>
+
+#include "bo.h"
+#include "dev.h"
+
+#define MAKE_YUV_601_Y(r, g, b) \
+ ((( 66 * (r) + 129 * (g) + 25 * (b) + 128) >> 8) + 16)
+#define MAKE_YUV_601_U(r, g, b) \
+ (((-38 * (r) - 74 * (g) + 112 * (b) + 128) >> 8) + 128)
+#define MAKE_YUV_601_V(r, g, b) \
+ (((112 * (r) - 94 * (g) - 18 * (b) + 128) >> 8) + 128)
+
+static void draw_rect_yuv(struct sp_bo *bo, uint32_t x, uint32_t y, uint32_t width,
+ uint32_t height, uint8_t a, uint8_t r, uint8_t g, uint8_t b)
+{
+ uint32_t i, j, xmax = x + width, ymax = y + height;
+
+ if (xmax > bo->width)
+ xmax = bo->width;
+ if (ymax > bo->height)
+ ymax = bo->height;
+
+ for (i = y; i < ymax; i++) {
+ uint8_t *luma = bo->map_addr + i * bo->pitch;
+
+ for (j = x; j < xmax; j++)
+ luma[j] = MAKE_YUV_601_Y(r, g, b);
+ }
+
+ for (i = y; i < ymax / 2; i++) {
+ uint8_t *chroma = bo->map_addr + (i + height) * bo->pitch;
+
+ for (j = x; j < xmax / 2; j++) {
+ chroma[j*2] = MAKE_YUV_601_U(r, g, b);
+ chroma[j*2 + 1] = MAKE_YUV_601_V(r, g, b);
+ }
+ }
+}
+
+void fill_bo(struct sp_bo *bo, uint8_t a, uint8_t r, uint8_t g, uint8_t b)
+{
+ if (bo->format == DRM_FORMAT_NV12)
+ draw_rect_yuv(bo, 0, 0, bo->width, bo->height, a, r, g, b);
+ else
+ draw_rect(bo, 0, 0, bo->width, bo->height, a, r, g, b);
+}
+
+void draw_rect(struct sp_bo *bo, uint32_t x, uint32_t y, uint32_t width,
+ uint32_t height, uint8_t a, uint8_t r, uint8_t g, uint8_t b)
+{
+ uint32_t i, j, xmax = x + width, ymax = y + height;
+
+ if (xmax > bo->width)
+ xmax = bo->width;
+ if (ymax > bo->height)
+ ymax = bo->height;
+
+ for (i = y; i < ymax; i++) {
+ uint8_t *row = bo->map_addr + i * bo->pitch;
+
+ for (j = x; j < xmax; j++) {
+ uint8_t *pixel = row + j * 4;
+
+ if (bo->format == DRM_FORMAT_ARGB8888 ||
+ bo->format == DRM_FORMAT_XRGB8888)
+ {
+ pixel[0] = b;
+ pixel[1] = g;
+ pixel[2] = r;
+ pixel[3] = a;
+ } else if (bo->format == DRM_FORMAT_RGBA8888) {
+ pixel[0] = r;
+ pixel[1] = g;
+ pixel[2] = b;
+ pixel[3] = a;
+ }
+ }
+ }
+}
+
+static int add_fb_sp_bo(struct sp_bo *bo, uint32_t format)
+{
+ int ret;
+ uint32_t handles[4], pitches[4], offsets[4];
+
+ handles[0] = bo->handle;
+ pitches[0] = bo->pitch;
+ offsets[0] = 0;
+ if (bo->format == DRM_FORMAT_NV12) {
+ handles[1] = bo->handle;
+ pitches[1] = pitches[0];
+ offsets[1] = pitches[0] * bo->height;
+ }
+
+ ret = drmModeAddFB2(bo->dev->fd, bo->width, bo->height,
+ format, handles, pitches, offsets,
+ &bo->fb_id, bo->flags);
+ if (ret) {
+ printf("failed to create fb ret=%d\n", ret);
+ return ret;
+ }
+ return 0;
+}
+
+static int map_sp_bo(struct sp_bo *bo)
+{
+ int ret;
+ struct drm_mode_map_dumb md;
+
+ if (bo->map_addr)
+ return 0;
+
+ md.handle = bo->handle;
+ ret = drmIoctl(bo->dev->fd, DRM_IOCTL_MODE_MAP_DUMB, &md);
+ if (ret) {
+ printf("failed to map sp_bo ret=%d\n", ret);
+ return ret;
+ }
+
+ bo->map_addr = mmap(NULL, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
+ bo->dev->fd, md.offset);
+ if (bo->map_addr == MAP_FAILED) {
+ printf("failed to map bo ret=%d\n", -errno);
+ return -errno;
+ }
+ return 0;
+}
+
+static int format_to_bpp(uint32_t format)
+{
+ switch (format) {
+ case DRM_FORMAT_NV12:
+ return 8;
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_RGBA8888:
+ default:
+ return 32;
+ }
+}
+
+struct sp_bo *create_sp_bo(struct sp_dev *dev, uint32_t width, uint32_t height,
+ uint32_t depth, uint32_t format, uint32_t flags)
+{
+ int ret;
+ struct drm_mode_create_dumb cd;
+ struct sp_bo *bo;
+
+ bo = calloc(1, sizeof(*bo));
+ if (!bo)
+ return NULL;
+
+ if (format == DRM_FORMAT_NV12)
+ cd.height = height * 3 / 2;
+ else
+ cd.height = height;
+
+ cd.width = width;
+ cd.bpp = format_to_bpp(format);
+ cd.flags = flags;
+
+ ret = drmIoctl(dev->fd, DRM_IOCTL_MODE_CREATE_DUMB, &cd);
+ if (ret) {
+ printf("failed to create sp_bo %d\n", ret);
+ goto err;
+ }
+
+ bo->dev = dev;
+ bo->width = width;
+ bo->height = height;
+ bo->depth = depth;
+ bo->bpp = format_to_bpp(format);
+ bo->format = format;
+ bo->flags = flags;
+
+ bo->handle = cd.handle;
+ bo->pitch = cd.pitch;
+ bo->size = cd.size;
+
+ ret = add_fb_sp_bo(bo, format);
+ if (ret) {
+ printf("failed to add fb ret=%d\n", ret);
+ goto err;
+ }
+
+ ret = map_sp_bo(bo);
+ if (ret) {
+ printf("failed to map bo ret=%d\n", ret);
+ goto err;
+ }
+
+ return bo;
+
+err:
+ free_sp_bo(bo);
+ return NULL;
+}
+
+void free_sp_bo(struct sp_bo *bo)
+{
+ int ret;
+ struct drm_mode_destroy_dumb dd;
+
+ if (!bo)
+ return;
+
+ if (bo->map_addr)
+ munmap(bo->map_addr, bo->size);
+
+ if (bo->fb_id) {
+ ret = drmModeRmFB(bo->dev->fd, bo->fb_id);
+ if (ret)
+ printf("Failed to rmfb ret=%d!\n", ret);
+ }
+
+ if (bo->handle) {
+ dd.handle = bo->handle;
+ ret = drmIoctl(bo->dev->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dd);
+ if (ret)
+ printf("Failed to destroy buffer ret=%d\n", ret);
+ }
+
+ free(bo);
+}
diff --git a/tests/planetest/bo.h b/tests/planetest/bo.h
new file mode 100644
index 0000000..7471e12
--- /dev/null
+++ b/tests/planetest/bo.h
@@ -0,0 +1,34 @@
+#ifndef __BO_H_INCLUDED__
+#define __BO_H_INCLUDED__
+
+#include <stdint.h>
+
+struct sp_dev;
+
+struct sp_bo {
+ struct sp_dev *dev;
+
+ uint32_t width;
+ uint32_t height;
+ uint32_t depth;
+ uint32_t bpp;
+ uint32_t format;
+ uint32_t flags;
+
+ uint32_t fb_id;
+ uint32_t handle;
+ void *map_addr;
+ uint32_t pitch;
+ uint32_t size;
+};
+
+struct sp_bo *create_sp_bo(struct sp_dev *dev, uint32_t width, uint32_t height,
+ uint32_t depth, uint32_t format, uint32_t flags);
+
+void fill_bo(struct sp_bo *bo, uint8_t a, uint8_t r, uint8_t g, uint8_t b);
+void draw_rect(struct sp_bo *bo, uint32_t x, uint32_t y, uint32_t width,
+ uint32_t height, uint8_t a, uint8_t r, uint8_t g, uint8_t b);
+
+void free_sp_bo(struct sp_bo *bo);
+
+#endif /* __BO_H_INCLUDED__ */
diff --git a/tests/planetest/dev.c b/tests/planetest/dev.c
new file mode 100644
index 0000000..bd0968c
--- /dev/null
+++ b/tests/planetest/dev.c
@@ -0,0 +1,367 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+
+#include <drm.h>
+#include <drm_fourcc.h>
+#include <errno.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include "bo.h"
+#include "dev.h"
+#include "modeset.h"
+
+static void show_usage(char *name)
+{
+ printf("Usage: %s [OPTION]\n", name);
+ printf(" -c, --card Index of dri card (ie: /dev/dri/cardN)\n");
+ printf(" -r, --crtc Index of crtc to use for test\n");
+ printf("\n\n");
+}
+
+void parse_arguments(int argc, char *argv[], int *card, int *crtc)
+{
+ static struct option options[] = {
+ { "card", required_argument, NULL, 'c' },
+ { "crtc", required_argument, NULL, 'r' },
+ { "help", no_argument, NULL, 'h' },
+ };
+ int option_index = 0;
+ int c;
+
+ *card = -1;
+ *crtc = -1;
+ do {
+ c = getopt_long(argc, argv, "c:r:h", options, &option_index);
+ switch (c) {
+ case 0:
+ case 'h':
+ show_usage(argv[0]);
+ exit(0);
+ case -1:
+ break;
+ case 'c':
+ if (optarg[0] < '0' || optarg[0] > '9') {
+ printf("Invalid card value '%s'!\n", optarg);
+ show_usage(argv[0]);
+ exit(-1);
+ }
+ *card = optarg[0] - '0';
+ break;
+ case 'r':
+ if (optarg[0] < '0' || optarg[0] > '9') {
+ printf("Invalid crtc value '%s'!\n", optarg);
+ show_usage(argv[0]);
+ exit(-1);
+ }
+ *crtc = optarg[0] - '0';
+ break;
+ }
+ } while (c != -1);
+
+ if (*card < 0 || *crtc < 0) {
+ show_usage(argv[0]);
+ exit(-1);
+ }
+}
+
+static uint32_t get_prop_id(struct sp_dev *dev,
+ drmModeObjectPropertiesPtr props, const char *name)
+{
+ drmModePropertyPtr p;
+ uint32_t i, prop_id = 0; /* Property ID should always be > 0 */
+
+ for (i = 0; !prop_id && i < props->count_props; i++) {
+ p = drmModeGetProperty(dev->fd, props->props[i]);
+ if (!strcmp(p->name, name))
+ prop_id = p->prop_id;
+ drmModeFreeProperty(p);
+ }
+ if (!prop_id)
+ printf("Could not find %s property\n", name);
+ return prop_id;
+}
+
+static int get_supported_format(struct sp_plane *plane, uint32_t *format)
+{
+ uint32_t i;
+
+ for (i = 0; i < plane->plane->count_formats; i++) {
+ if (plane->plane->formats[i] == DRM_FORMAT_XRGB8888 ||
+ plane->plane->formats[i] == DRM_FORMAT_ARGB8888 ||
+ plane->plane->formats[i] == DRM_FORMAT_RGBA8888 ||
+ plane->plane->formats[i] == DRM_FORMAT_NV12) {
+ *format = plane->plane->formats[i];
+ return 0;
+ }
+ }
+ printf("No suitable formats found!\n");
+ return -ENOENT;
+}
+
+struct sp_dev *create_sp_dev(int card)
+{
+ struct sp_dev *dev;
+ int ret, fd, i, j;
+ drmModeRes *r = NULL;
+ drmModePlaneRes *pr = NULL;
+ char card_path[256];
+
+ snprintf(card_path, sizeof(card_path), "/dev/dri/card%d", card);
+
+ fd = open(card_path, O_RDWR);
+ if (fd < 0) {
+ printf("failed to open card0\n");
+ return NULL;
+ }
+
+ dev = calloc(1, sizeof(*dev));
+ if (!dev) {
+ printf("failed to allocate dev\n");
+ return NULL;
+ }
+
+ dev->fd = fd;
+
+ ret = drmSetClientCap(dev->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
+ if (ret) {
+ printf("failed to set client cap\n");
+ goto err;
+ }
+
+ ret = drmSetClientCap(dev->fd, DRM_CLIENT_CAP_ATOMIC, 1);
+ if (ret) {
+ printf("Failed to set atomic cap %d", ret);
+ goto err;
+ }
+
+ r = drmModeGetResources(dev->fd);
+ if (!r) {
+ printf("failed to get r\n");
+ goto err;
+ }
+
+ dev->num_connectors = r->count_connectors;
+ dev->connectors = calloc(dev->num_connectors,
+ sizeof(struct sp_connector));
+ if (!dev->connectors) {
+ printf("failed to allocate connectors\n");
+ goto err;
+ }
+ for (i = 0; i < dev->num_connectors; i++) {
+ drmModeObjectPropertiesPtr props;
+ dev->connectors[i].conn = drmModeGetConnector(dev->fd,
+ r->connectors[i]);
+ if (!dev->connectors[i].conn) {
+ printf("failed to get connector %d\n", i);
+ goto err;
+ }
+
+ props = drmModeObjectGetProperties(dev->fd, r->connectors[i],
+ DRM_MODE_OBJECT_CONNECTOR);
+ if (!props) {
+ printf("failed to get connector properties\n");
+ goto err;
+ }
+
+ dev->connectors[i].crtc_id_pid = get_prop_id(dev, props,
+ "CRTC_ID");
+ drmModeFreeObjectProperties(props);
+ if (!dev->connectors[i].crtc_id_pid)
+ goto err;
+ }
+
+ dev->num_encoders = r->count_encoders;
+ dev->encoders = calloc(dev->num_encoders, sizeof(*dev->encoders));
+ if (!dev->encoders) {
+ printf("failed to allocate encoders\n");
+ goto err;
+ }
+ for (i = 0; i < dev->num_encoders; i++) {
+ dev->encoders[i] = drmModeGetEncoder(dev->fd, r->encoders[i]);
+ if (!dev->encoders[i]) {
+ printf("failed to get encoder %d\n", i);
+ goto err;
+ }
+ }
+
+ dev->num_crtcs = r->count_crtcs;
+ dev->crtcs = calloc(dev->num_crtcs, sizeof(struct sp_crtc));
+ if (!dev->crtcs) {
+ printf("failed to allocate crtcs\n");
+ goto err;
+ }
+ for (i = 0; i < dev->num_crtcs; i++) {
+ drmModeObjectPropertiesPtr props;
+
+ dev->crtcs[i].crtc = drmModeGetCrtc(dev->fd, r->crtcs[i]);
+ if (!dev->crtcs[i].crtc) {
+ printf("failed to get crtc %d\n", i);
+ goto err;
+ }
+ dev->crtcs[i].pipe = i;
+ dev->crtcs[i].num_planes = 0;
+
+ props = drmModeObjectGetProperties(dev->fd, r->crtcs[i],
+ DRM_MODE_OBJECT_CRTC);
+ if (!props) {
+ printf("failed to get crtc properties\n");
+ goto err;
+ }
+
+ dev->crtcs[i].mode_pid = get_prop_id(dev, props, "MODE_ID");
+ dev->crtcs[i].active_pid = get_prop_id(dev, props, "ACTIVE");
+ drmModeFreeObjectProperties(props);
+ if (!dev->crtcs[i].mode_pid || !dev->crtcs[i].active_pid)
+ goto err;
+ }
+
+ pr = drmModeGetPlaneResources(dev->fd);
+ if (!pr) {
+ printf("failed to get plane resources\n");
+ goto err;
+ }
+ dev->num_planes = pr->count_planes;
+ dev->planes = calloc(dev->num_planes, sizeof(struct sp_plane));
+ for(i = 0; i < dev->num_planes; i++) {
+ drmModeObjectPropertiesPtr props;
+ struct sp_plane *plane = &dev->planes[i];
+
+ plane->dev = dev;
+ plane->plane = drmModeGetPlane(dev->fd, pr->planes[i]);
+ if (!plane->plane) {
+ printf("failed to get plane %d\n", i);
+ goto err;
+ }
+ plane->bo = NULL;
+ plane->in_use = 0;
+
+ ret = get_supported_format(plane, &plane->format);
+ if (ret) {
+ printf("failed to get supported format: %d\n", ret);
+ goto err;
+ }
+
+ for (j = 0; j < dev->num_crtcs; j++) {
+ if (plane->plane->possible_crtcs & (1 << j))
+ dev->crtcs[j].num_planes++;
+ }
+
+ props = drmModeObjectGetProperties(dev->fd, pr->planes[i],
+ DRM_MODE_OBJECT_PLANE);
+ if (!props) {
+ printf("failed to get plane properties\n");
+ goto err;
+ }
+ plane->crtc_pid = get_prop_id(dev, props, "CRTC_ID");
+ if (!plane->crtc_pid) {
+ drmModeFreeObjectProperties(props);
+ goto err;
+ }
+ plane->fb_pid = get_prop_id(dev, props, "FB_ID");
+ if (!plane->fb_pid) {
+ drmModeFreeObjectProperties(props);
+ goto err;
+ }
+ plane->crtc_x_pid = get_prop_id(dev, props, "CRTC_X");
+ if (!plane->crtc_x_pid) {
+ drmModeFreeObjectProperties(props);
+ goto err;
+ }
+ plane->crtc_y_pid = get_prop_id(dev, props, "CRTC_Y");
+ if (!plane->crtc_y_pid) {
+ drmModeFreeObjectProperties(props);
+ goto err;
+ }
+ plane->crtc_w_pid = get_prop_id(dev, props, "CRTC_W");
+ if (!plane->crtc_w_pid) {
+ drmModeFreeObjectProperties(props);
+ goto err;
+ }
+ plane->crtc_h_pid = get_prop_id(dev, props, "CRTC_H");
+ if (!plane->crtc_h_pid) {
+ drmModeFreeObjectProperties(props);
+ goto err;
+ }
+ plane->src_x_pid = get_prop_id(dev, props, "SRC_X");
+ if (!plane->src_x_pid) {
+ drmModeFreeObjectProperties(props);
+ goto err;
+ }
+ plane->src_y_pid = get_prop_id(dev, props, "SRC_Y");
+ if (!plane->src_y_pid) {
+ drmModeFreeObjectProperties(props);
+ goto err;
+ }
+ plane->src_w_pid = get_prop_id(dev, props, "SRC_W");
+ if (!plane->src_w_pid) {
+ drmModeFreeObjectProperties(props);
+ goto err;
+ }
+ plane->src_h_pid = get_prop_id(dev, props, "SRC_H");
+ if (!plane->src_h_pid) {
+ drmModeFreeObjectProperties(props);
+ goto err;
+ }
+ drmModeFreeObjectProperties(props);
+ }
+
+ if (pr)
+ drmModeFreePlaneResources(pr);
+ if (r)
+ drmModeFreeResources(r);
+
+ return dev;
+err:
+ if (pr)
+ drmModeFreePlaneResources(pr);
+ if (r)
+ drmModeFreeResources(r);
+ destroy_sp_dev(dev);
+ return NULL;
+}
+
+void destroy_sp_dev(struct sp_dev *dev)
+{
+ int i;
+
+ if (dev->planes) {
+ for (i = 0; i< dev->num_planes; i++) {
+ if (dev->planes[i].in_use)
+ put_sp_plane(&dev->planes[i]);
+ if (dev->planes[i].plane)
+ drmModeFreePlane(dev->planes[i].plane);
+ if (dev->planes[i].bo)
+ free_sp_bo(dev->planes[i].bo);
+ }
+ free(dev->planes);
+ }
+ if (dev->crtcs) {
+ for (i = 0; i< dev->num_crtcs; i++) {
+ if (dev->crtcs[i].crtc)
+ drmModeFreeCrtc(dev->crtcs[i].crtc);
+ }
+ free(dev->crtcs);
+ }
+ if (dev->encoders) {
+ for (i = 0; i< dev->num_encoders; i++) {
+ if (dev->encoders[i])
+ drmModeFreeEncoder(dev->encoders[i]);
+ }
+ free(dev->encoders);
+ }
+ if (dev->connectors) {
+ for (i = 0; i< dev->num_connectors; i++) {
+ if (dev->connectors[i].conn)
+ drmModeFreeConnector(dev->connectors[i].conn);
+ }
+ free(dev->connectors);
+ }
+
+ close(dev->fd);
+ free(dev);
+}
diff --git a/tests/planetest/dev.h b/tests/planetest/dev.h
new file mode 100644
index 0000000..04dec79
--- /dev/null
+++ b/tests/planetest/dev.h
@@ -0,0 +1,65 @@
+#ifndef __DEV_H_INCLUDED__
+#define __DEV_H_INCLUDED__
+
+#include <stdint.h>
+#include <xf86drmMode.h>
+
+struct sp_bo;
+struct sp_dev;
+
+struct sp_plane {
+ struct sp_dev *dev;
+ drmModePlanePtr plane;
+ struct sp_bo *bo;
+ int in_use;
+ uint32_t format;
+
+ /* Property ID's */
+ uint32_t crtc_pid;
+ uint32_t fb_pid;
+ uint32_t zpos_pid;
+ uint32_t crtc_x_pid;
+ uint32_t crtc_y_pid;
+ uint32_t crtc_w_pid;
+ uint32_t crtc_h_pid;
+ uint32_t src_x_pid;
+ uint32_t src_y_pid;
+ uint32_t src_w_pid;
+ uint32_t src_h_pid;
+};
+
+struct sp_connector {
+ drmModeConnectorPtr conn;
+ uint32_t crtc_id_pid;
+};
+
+struct sp_crtc {
+ drmModeCrtcPtr crtc;
+ int pipe;
+ int num_planes;
+ uint32_t mode_pid;
+ uint32_t active_pid;
+};
+
+struct sp_dev {
+ int fd;
+
+ int num_connectors;
+ struct sp_connector *connectors;
+
+ int num_encoders;
+ drmModeEncoderPtr *encoders;
+
+ int num_crtcs;
+ struct sp_crtc *crtcs;
+
+ int num_planes;
+ struct sp_plane *planes;
+};
+
+void parse_arguments(int argc, char *argv[], int *card, int *crtc);
+
+struct sp_dev *create_sp_dev(int card);
+void destroy_sp_dev(struct sp_dev *dev);
+
+#endif /* __DEV_H_INCLUDED__ */
diff --git a/tests/planetest/modeset.c b/tests/planetest/modeset.c
new file mode 100644
index 0000000..037814e
--- /dev/null
+++ b/tests/planetest/modeset.c
@@ -0,0 +1,232 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+#include <drm_fourcc.h>
+
+#include "modeset.h"
+#include "bo.h"
+#include "dev.h"
+
+static int set_crtc_mode(struct sp_dev *dev, struct sp_crtc *crtc,
+ struct sp_connector *conn, drmModeModeInfoPtr mode)
+{
+ int ret;
+ struct drm_mode_create_blob create_blob;
+ drmModePropertySetPtr pset;
+
+ memset(&create_blob, 0, sizeof(create_blob));
+ create_blob.length = sizeof(struct drm_mode_modeinfo);
+ create_blob.data = (__u64)(uintptr_t)mode;
+
+ ret = drmIoctl(dev->fd, DRM_IOCTL_MODE_CREATEPROPBLOB, &create_blob);
+ if (ret) {
+ printf("Failed to create mode property blob %d", ret);
+ return ret;
+ }
+
+ pset = drmModePropertySetAlloc();
+ if (!pset) {
+ printf("Failed to allocate property set");
+ return -1;
+ }
+
+ ret = drmModePropertySetAdd(pset, crtc->crtc->crtc_id,
+ crtc->mode_pid, create_blob.blob_id) ||
+ drmModePropertySetAdd(pset, crtc->crtc->crtc_id,
+ crtc->active_pid, 1) ||
+ drmModePropertySetAdd(pset, conn->conn->connector_id,
+ conn->crtc_id_pid, crtc->crtc->crtc_id);
+ if (ret) {
+ printf("Failed to add blob %d to pset", create_blob.blob_id);
+ drmModePropertySetFree(pset);
+ return ret;
+ }
+
+ ret = drmModePropertySetCommit(dev->fd, DRM_MODE_ATOMIC_ALLOW_MODESET,
+ NULL, pset);
+
+ drmModePropertySetFree(pset);
+
+ if (ret) {
+ printf("Failed to commit pset ret=%d\n", ret);
+ return ret;
+ }
+
+ memcpy(&crtc->crtc->mode, mode, sizeof(struct drm_mode_modeinfo));
+ crtc->crtc->mode_valid = 1;
+ return 0;
+}
+
+int initialize_screens(struct sp_dev *dev)
+{
+ int ret, i, j;
+ unsigned crtc_mask = 0;
+
+ for (i = 0; i < dev->num_connectors; i++) {
+ struct sp_connector *c = &dev->connectors[i];
+ drmModeModeInfoPtr m = NULL;
+ drmModeEncoderPtr e = NULL;
+ struct sp_crtc *cr = NULL;
+
+ if (c->conn->connection != DRM_MODE_CONNECTED)
+ continue;
+
+ if (!c->conn->count_modes) {
+ printf("connector has no modes, skipping\n");
+ continue;
+ }
+
+ /* Take the first unless there's a preferred mode */
+ m = &c->conn->modes[0];
+ for (j = 0; j < c->conn->count_modes; j++) {
+ drmModeModeInfoPtr tmp_m = &c->conn->modes[j];
+
+ if (!(tmp_m->type & DRM_MODE_TYPE_PREFERRED))
+ continue;
+
+ m = tmp_m;
+ break;
+ }
+
+ if (!c->conn->count_encoders) {
+ printf("no possible encoders for connector\n");
+ continue;
+ }
+
+ for (j = 0; j < dev->num_encoders; j++) {
+ e = dev->encoders[j];
+ if (e->encoder_id == c->conn->encoders[0])
+ break;
+ }
+ if (j == dev->num_encoders) {
+ printf("could not find encoder for the connector\n");
+ continue;
+ }
+
+ for (j = 0; j < dev->num_crtcs; j++) {
+ if ((1 << j) & crtc_mask)
+ continue;
+
+ cr = &dev->crtcs[j];
+
+ if ((1 << j) & e->possible_crtcs)
+ break;
+ }
+ if (j == dev->num_crtcs) {
+ printf("could not find crtc for the encoder\n");
+ continue;
+ }
+
+ ret = set_crtc_mode(dev, cr, c, m);
+ if (ret) {
+ printf("failed to set mode!\n");
+ continue;
+ }
+ crtc_mask |= 1 << j;
+ }
+ return 0;
+}
+
+struct sp_plane *get_sp_plane(struct sp_dev *dev, struct sp_crtc *crtc)
+{
+ int i;
+
+ for(i = 0; i < dev->num_planes; i++) {
+ struct sp_plane *p = &dev->planes[i];
+
+ if (p->in_use)
+ continue;
+
+ if (!(p->plane->possible_crtcs & (1 << crtc->pipe)))
+ continue;
+
+ p->in_use = 1;
+ return p;
+ }
+ return NULL;
+}
+
+void put_sp_plane(struct sp_plane *plane)
+{
+ drmModePlanePtr p;
+
+ /* Get the latest plane information (most notably the crtc_id) */
+ p = drmModeGetPlane(plane->dev->fd, plane->plane->plane_id);
+ if (p)
+ plane->plane = p;
+
+ if (plane->bo) {
+ free_sp_bo(plane->bo);
+ plane->bo = NULL;
+ }
+ plane->in_use = 0;
+}
+
+int set_sp_plane(struct sp_dev *dev, struct sp_plane *plane,
+ struct sp_crtc *crtc, int x, int y)
+{
+ int ret;
+ uint32_t w, h;
+
+ w = plane->bo->width;
+ h = plane->bo->height;
+
+ if ((w + x) > crtc->crtc->mode.hdisplay)
+ w = crtc->crtc->mode.hdisplay - x;
+ if ((h + y) > crtc->crtc->mode.vdisplay)
+ h = crtc->crtc->mode.vdisplay - y;
+
+ ret = drmModeSetPlane(dev->fd, plane->plane->plane_id,
+ crtc->crtc->crtc_id, plane->bo->fb_id, 0, x, y, w, h,
+ 0, 0, w << 16, h << 16);
+ if (ret) {
+ printf("failed to set plane to crtc ret=%d\n", ret);
+ return ret;
+ }
+
+ return ret;
+}
+int set_sp_plane_pset(struct sp_dev *dev, struct sp_plane *plane,
+ drmModePropertySetPtr pset, struct sp_crtc *crtc, int x, int y)
+{
+ int ret;
+ uint32_t w, h;
+
+ w = plane->bo->width;
+ h = plane->bo->height;
+
+ if ((w + x) > crtc->crtc->mode.hdisplay)
+ w = crtc->crtc->mode.hdisplay - x;
+ if ((h + y) > crtc->crtc->mode.vdisplay)
+ h = crtc->crtc->mode.vdisplay - y;
+
+ ret = drmModePropertySetAdd(pset, plane->plane->plane_id,
+ plane->crtc_pid, crtc->crtc->crtc_id)
+ || drmModePropertySetAdd(pset, plane->plane->plane_id,
+ plane->fb_pid, plane->bo->fb_id)
+ || drmModePropertySetAdd(pset, plane->plane->plane_id,
+ plane->crtc_x_pid, x)
+ || drmModePropertySetAdd(pset, plane->plane->plane_id,
+ plane->crtc_y_pid, y)
+ || drmModePropertySetAdd(pset, plane->plane->plane_id,
+ plane->crtc_w_pid, w)
+ || drmModePropertySetAdd(pset, plane->plane->plane_id,
+ plane->crtc_h_pid, h)
+ || drmModePropertySetAdd(pset, plane->plane->plane_id,
+ plane->src_x_pid, 0)
+ || drmModePropertySetAdd(pset, plane->plane->plane_id,
+ plane->src_y_pid, 0)
+ || drmModePropertySetAdd(pset, plane->plane->plane_id,
+ plane->src_w_pid, w << 16)
+ || drmModePropertySetAdd(pset, plane->plane->plane_id,
+ plane->src_h_pid, h << 16);
+ if (ret) {
+ printf("failed to add properties to the set\n");
+ return -1;
+ }
+
+ return ret;
+}
diff --git a/tests/planetest/modeset.h b/tests/planetest/modeset.h
new file mode 100644
index 0000000..7e96574
--- /dev/null
+++ b/tests/planetest/modeset.h
@@ -0,0 +1,19 @@
+#ifndef __MODESET_H_INCLUDED__
+#define __MODESET_H_INCLUDED__
+
+struct sp_dev;
+struct sp_crtc;
+
+int initialize_screens(struct sp_dev *dev);
+
+
+struct sp_plane *get_sp_plane(struct sp_dev *dev, struct sp_crtc *crtc);
+void put_sp_plane(struct sp_plane *plane);
+
+int set_sp_plane(struct sp_dev *dev, struct sp_plane *plane,
+ struct sp_crtc *crtc, int x, int y);
+
+int set_sp_plane_pset(struct sp_dev *dev, struct sp_plane *plane,
+ drmModePropertySetPtr pset, struct sp_crtc *crtc, int x, int y);
+
+#endif /* __MODESET_H_INCLUDED__ */
diff --git a/tests/planetest/planetest.c b/tests/planetest/planetest.c
new file mode 100644
index 0000000..5e187c9
--- /dev/null
+++ b/tests/planetest/planetest.c
@@ -0,0 +1,116 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/select.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <time.h>
+#include <errno.h>
+
+#include <xf86drm.h>
+
+#include "dev.h"
+#include "bo.h"
+#include "modeset.h"
+
+static int terminate = 0;
+
+static void sigint_handler(int arg)
+{
+ terminate = 1;
+}
+
+static void incrementor(int *inc, int *val, int increment, int lower, int upper)
+{
+ if(*inc > 0)
+ *inc = *val + increment >= upper ? -1 : 1;
+ else
+ *inc = *val - increment <= lower ? 1 : -1;
+ *val += *inc * increment;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret, i, j, num_test_planes;
+ int x_inc = 1, x = 0, y_inc = 1, y = 0;
+ uint32_t plane_w = 128, plane_h = 128;
+ struct sp_dev *dev;
+ struct sp_plane **plane = NULL;
+ struct sp_crtc *test_crtc;
+ int card = 0, crtc = 0;
+
+ signal(SIGINT, sigint_handler);
+
+ parse_arguments(argc, argv, &card, &crtc);
+
+ dev = create_sp_dev(card);
+ if (!dev) {
+ printf("Failed to create sp_dev\n");
+ return -1;
+ }
+
+ if (crtc >= dev->num_crtcs) {
+ printf("Invalid crtc %d (num=%d)\n", crtc, dev->num_crtcs);
+ return -1;
+ }
+
+ ret = initialize_screens(dev);
+ if (ret) {
+ printf("Failed to initialize screens\n");
+ goto out;
+ }
+ test_crtc = &dev->crtcs[crtc];
+
+ plane = calloc(dev->num_planes, sizeof(*plane));
+ if (!plane) {
+ printf("Failed to allocate plane array\n");
+ goto out;
+ }
+
+ /* Create our planes */
+ num_test_planes = test_crtc->num_planes;
+ for (i = 0; i < num_test_planes; i++) {
+ plane[i] = get_sp_plane(dev, test_crtc);
+ if (!plane[i]) {
+ printf("no unused planes available\n");
+ goto out;
+ }
+
+ plane[i]->bo = create_sp_bo(dev, plane_w, plane_h, 16,
+ plane[i]->format, 0);
+ if (!plane[i]->bo) {
+ printf("failed to create plane bo\n");
+ goto out;
+ }
+
+ fill_bo(plane[i]->bo, 0xFF, 0xFF, 0xFF, 0xFF);
+ }
+
+ while (!terminate) {
+ incrementor(&x_inc, &x, 5, 0,
+ test_crtc->crtc->mode.hdisplay - plane_w);
+ incrementor(&y_inc, &y, 5, 0, test_crtc->crtc->mode.vdisplay -
+ plane_h * num_test_planes);
+
+ for (j = 0; j < num_test_planes; j++) {
+ ret = set_sp_plane(dev, plane[j], test_crtc,
+ x, y + j * plane_h);
+ if (ret) {
+ printf("failed to set plane %d %d\n", j, ret);
+ goto out;
+ }
+ }
+ usleep(15 * 1000);
+ }
+
+ for (i = 0; i < num_test_planes; i++)
+ put_sp_plane(plane[i]);
+
+out:
+ destroy_sp_dev(dev);
+ free(plane);
+ return ret;
+}
diff --git a/tests/proptest/Android.mk b/tests/proptest/Android.mk
index 91a590f..588fbed 100644
--- a/tests/proptest/Android.mk
+++ b/tests/proptest/Android.mk
@@ -10,5 +10,7 @@
LOCAL_SHARED_LIBRARIES := libdrm
LOCAL_STATIC_LIBRARIES := libdrm_util
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/..
+
include $(LIBDRM_COMMON_MK)
include $(BUILD_EXECUTABLE)
diff --git a/xf86drmMode.c b/xf86drmMode.c
index 0266bc1..e1c9974 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -1188,6 +1188,275 @@
return DRM_IOCTL(fd, DRM_IOCTL_MODE_OBJ_SETPROPERTY, &prop);
}
+typedef struct _drmModePropertySetItem drmModePropertySetItem, *drmModePropertySetItemPtr;
+
+struct _drmModePropertySetItem {
+ uint32_t object_id;
+ uint32_t property_id;
+ bool is_blob;
+ uint64_t value;
+ void *blob;
+ drmModePropertySetItemPtr next;
+};
+
+struct _drmModePropertySet {
+ unsigned int count_objs;
+ unsigned int count_props;
+ unsigned int count_blobs;
+ drmModePropertySetItem list;
+};
+
+drmModePropertySetPtr drmModePropertySetAlloc(void)
+{
+ drmModePropertySetPtr set;
+
+ set = drmMalloc(sizeof *set);
+ if (!set)
+ return NULL;
+
+ set->list.next = NULL;
+ set->count_props = 0;
+ set->count_objs = 0;
+
+ return set;
+}
+
+int drmModePropertySetAdd(drmModePropertySetPtr set,
+ uint32_t object_id,
+ uint32_t property_id,
+ uint64_t value)
+{
+ drmModePropertySetItemPtr prev = &set->list;
+ bool new_obj = false;
+
+ /* keep it sorted by object_id and property_id */
+ while (prev->next) {
+ if (prev->next->object_id > object_id)
+ break;
+
+ if (prev->next->object_id == object_id &&
+ prev->next->property_id >= property_id)
+ break;
+
+ prev = prev->next;
+ }
+
+ if ((prev == &set->list || prev->object_id != object_id) &&
+ (!prev->next || prev->next->object_id != object_id))
+ new_obj = true;
+
+ /* replace or add? */
+ if (prev->next &&
+ prev->next->object_id == object_id &&
+ prev->next->property_id == property_id) {
+ drmModePropertySetItemPtr item = prev->next;
+
+ if (item->is_blob)
+ return -EINVAL;
+
+ item->value = value;
+ } else {
+ drmModePropertySetItemPtr item;
+
+ item = drmMalloc(sizeof *item);
+ if (!item)
+ return -1;
+
+ item->object_id = object_id;
+ item->property_id = property_id;
+ item->value = value;
+ item->is_blob = false;
+ item->blob = NULL;
+
+ item->next = prev->next;
+ prev->next = item;
+
+ set->count_props++;
+ }
+
+ if (new_obj)
+ set->count_objs++;
+
+ return 0;
+}
+
+int drmModePropertySetAddBlob(drmModePropertySetPtr set,
+ uint32_t object_id,
+ uint32_t property_id,
+ uint64_t length,
+ void *data)
+{
+ drmModePropertySetItemPtr prev = &set->list;
+ bool new_obj = false;
+
+ /* keep it sorted by object_id and property_id */
+ while (prev->next) {
+ if (prev->next->object_id > object_id)
+ break;
+
+ if (prev->next->object_id == object_id &&
+ prev->next->property_id >= property_id)
+ break;
+
+ prev = prev->next;
+ }
+
+ if ((prev == &set->list || prev->object_id != object_id) &&
+ (!prev->next || prev->next->object_id != object_id))
+ new_obj = true;
+
+ /* replace or add? */
+ if (prev->next &&
+ prev->next->object_id == object_id &&
+ prev->next->property_id == property_id) {
+ drmModePropertySetItemPtr item = prev->next;
+
+ if (!item->is_blob)
+ return -EINVAL;
+
+ item->value = length;
+ item->blob = data;
+ } else {
+ drmModePropertySetItemPtr item;
+
+ item = drmMalloc(sizeof *item);
+ if (!item)
+ return -1;
+
+ item->object_id = object_id;
+ item->property_id = property_id;
+ item->is_blob = true;
+ item->value = length;
+ item->blob = data;
+
+ item->next = prev->next;
+ prev->next = item;
+
+ set->count_props++;
+ set->count_blobs++;
+ }
+
+ if (new_obj)
+ set->count_objs++;
+
+ return 0;
+}
+
+void drmModePropertySetFree(drmModePropertySetPtr set)
+{
+ drmModePropertySetItemPtr item;
+
+ if (!set)
+ return;
+
+ item = set->list.next;
+
+ while (item) {
+ drmModePropertySetItemPtr next = item->next;
+
+ drmFree(item);
+
+ item = next;
+ }
+
+ drmFree(set);
+}
+
+int drmModePropertySetCommit(int fd, uint32_t flags, void *user_data,
+ drmModePropertySetPtr set)
+{
+ drmModePropertySetItemPtr item;
+ uint32_t *objs_ptr = NULL;
+ uint32_t *count_props_ptr = NULL;
+ uint32_t *props_ptr = NULL;
+ uint64_t *prop_values_ptr = NULL;
+ uint64_t *blob_values_ptr = NULL;
+ struct drm_mode_atomic atomic = { 0 };
+ unsigned int obj_idx = 0;
+ unsigned int prop_idx = 0;
+ unsigned int blob_idx = 0;
+ int ret = -1;
+
+ if (!set)
+ return -1;
+
+ objs_ptr = drmMalloc(set->count_objs * sizeof objs_ptr[0]);
+ if (!objs_ptr) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ count_props_ptr = drmMalloc(set->count_objs * sizeof count_props_ptr[0]);
+ if (!count_props_ptr) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ props_ptr = drmMalloc(set->count_props * sizeof props_ptr[0]);
+ if (!props_ptr) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ prop_values_ptr = drmMalloc(set->count_props * sizeof prop_values_ptr[0]);
+ if (!prop_values_ptr) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ blob_values_ptr = drmMalloc(set->count_blobs * sizeof blob_values_ptr[0]);
+ if (!blob_values_ptr) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ item = set->list.next;
+
+ while (item) {
+ int count_props = 0;
+ drmModePropertySetItemPtr next = item;
+
+ objs_ptr[obj_idx] = item->object_id;
+
+ while (next && next->object_id == item->object_id) {
+ props_ptr[prop_idx] = next->property_id;
+ prop_values_ptr[prop_idx] = next->value;
+ prop_idx++;
+
+ if (next->is_blob)
+ blob_values_ptr[blob_idx++] = VOID2U64(next->blob);
+
+ count_props++;
+
+ next = next->next;
+ }
+
+ count_props_ptr[obj_idx++] = count_props;
+
+ item = next;
+ }
+
+ atomic.count_objs = set->count_objs;
+ atomic.flags = flags;
+ atomic.objs_ptr = VOID2U64(objs_ptr);
+ atomic.count_props_ptr = VOID2U64(count_props_ptr);
+ atomic.props_ptr = VOID2U64(props_ptr);
+ atomic.prop_values_ptr = VOID2U64(prop_values_ptr);
+// TODO:
+// atomic.blob_values_ptr = VOID2U64(blob_values_ptr);
+ atomic.user_data = VOID2U64(user_data);
+
+ ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ATOMIC, &atomic);
+
+out:
+ drmFree(objs_ptr);
+ drmFree(count_props_ptr);
+ drmFree(props_ptr);
+ drmFree(prop_values_ptr);
+
+ return ret;
+}
+
typedef struct _drmModeAtomicReqItem drmModeAtomicReqItem, *drmModeAtomicReqItemPtr;
struct _drmModeAtomicReqItem {
diff --git a/xf86drmMode.h b/xf86drmMode.h
index 5b390d9..9d73be9 100644
--- a/xf86drmMode.h
+++ b/xf86drmMode.h
@@ -498,6 +498,25 @@
uint64_t value);
+typedef struct _drmModePropertySet drmModePropertySet, *drmModePropertySetPtr;
+
+extern drmModePropertySetPtr drmModePropertySetAlloc(void);
+
+extern int drmModePropertySetAdd(drmModePropertySetPtr set,
+ uint32_t object_id,
+ uint32_t property_id,
+ uint64_t value);
+extern int drmModePropertySetAddBlob(drmModePropertySetPtr set,
+ uint32_t object_id,
+ uint32_t property_id,
+ uint64_t length,
+ void *blob);
+
+extern int drmModePropertySetCommit(int fd, uint32_t flags,
+ void *user_data, drmModePropertySetPtr set);
+
+extern void drmModePropertySetFree(drmModePropertySetPtr set);
+
typedef struct _drmModeAtomicReq drmModeAtomicReq, *drmModeAtomicReqPtr;
extern drmModeAtomicReqPtr drmModeAtomicAlloc(void);