diff mbox

[RFC,2/2] drm: Add HDMI helpers

Message ID 1353510113-4388-3-git-send-email-thierry.reding@avionic-design.de (mailing list archive)
State New, archived
Headers show

Commit Message

Thierry Reding Nov. 21, 2012, 3:01 p.m. UTC
Add a generic helper to fill in an HDMI AVI infoframe with data
extracted from a DRM display mode.

Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
---
 drivers/gpu/drm/Kconfig    |   7 +++
 drivers/gpu/drm/Makefile   |   1 +
 drivers/gpu/drm/drm_hdmi.c | 107 +++++++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_hdmi.h     |  18 ++++++++
 4 files changed, 133 insertions(+)
 create mode 100644 drivers/gpu/drm/drm_hdmi.c
 create mode 100644 include/drm/drm_hdmi.h
diff mbox

Patch

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 983201b..94a4623 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -69,6 +69,13 @@  config DRM_KMS_CMA_HELPER
 	help
 	  Choose this if you need the KMS CMA helper functions
 
+config DRM_HDMI
+	bool
+	depends on DRM
+	select HDMI
+	help
+	  Choose this if you need the HDMI helper functions
+
 config DRM_TDFX
 	tristate "3dfx Banshee/Voodoo3+"
 	depends on DRM && PCI
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 0bfda06..330451b 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -16,6 +16,7 @@  drm-y       :=	drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
 
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
+drm-$(CONFIG_DRM_HDMI) += drm_hdmi.o
 
 drm-usb-y   := drm_usb.o
 
diff --git a/drivers/gpu/drm/drm_hdmi.c b/drivers/gpu/drm/drm_hdmi.c
new file mode 100644
index 0000000..1a8d914
--- /dev/null
+++ b/drivers/gpu/drm/drm_hdmi.c
@@ -0,0 +1,107 @@ 
+/*
+ * Copyright (C) 2012 Avionic Design GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/hdmi.h>
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_hdmi.h>
+
+struct hdmi_cea_mode {
+	unsigned char vic;
+	unsigned int width;
+	unsigned int height;
+	unsigned int refresh;
+	enum hdmi_picture_aspect aspect;
+	bool interlaced;
+	unsigned int repeat_min;
+	unsigned int repeat_max;
+};
+
+static const struct hdmi_cea_mode hdmi_cea_modes[] = {
+	{  1,  640,  480,  60, HDMI_PICTURE_ASPECT_4_3,  false, 0, 0 },
+	{  2,  720,  480,  60, HDMI_PICTURE_ASPECT_NONE, false, 0, 0 },
+	{  4, 1280,  720,  60, HDMI_PICTURE_ASPECT_16_9, false, 0, 0 },
+	{  5, 1920, 1080,  60, HDMI_PICTURE_ASPECT_16_9, true,  0, 0 },
+	{  6,  720,  480,  60, HDMI_PICTURE_ASPECT_NONE, true,  1, 1 },
+	{  8,  720,  240,  60, HDMI_PICTURE_ASPECT_NONE, false, 1, 1 },
+	{ 10, 2880,  480,  60, HDMI_PICTURE_ASPECT_NONE, true,  0, 9 },
+	{ 12, 2880,  240,  60, HDMI_PICTURE_ASPECT_NONE, false, 0, 9 },
+	{ 14, 1440,  480,  60, HDMI_PICTURE_ASPECT_NONE, false, 0, 1 },
+	{ 16, 1920, 1080,  60, HDMI_PICTURE_ASPECT_16_9, false, 0, 0 },
+	{ 17,  720,  576,  50, HDMI_PICTURE_ASPECT_NONE, false, 0, 0 },
+	{ 19, 1280,  720,  50, HDMI_PICTURE_ASPECT_16_9, false, 0, 0 },
+	{ 20, 1920, 1080,  50, HDMI_PICTURE_ASPECT_16_9, true,  0, 0 },
+	{ 21,  720,  576,  50, HDMI_PICTURE_ASPECT_NONE, true,  1, 1 },
+	{ 23,  720,  288,  50, HDMI_PICTURE_ASPECT_NONE, false, 1, 1 },
+	{ 25, 2880,  576,  50, HDMI_PICTURE_ASPECT_NONE, true,  0, 9 },
+	{ 27, 2880,  288,  50, HDMI_PICTURE_ASPECT_NONE, false, 0, 9 },
+	{ 29, 1440,  576,  50, HDMI_PICTURE_ASPECT_NONE, false, 0, 1 },
+	{ 31, 1920, 1080,  50, HDMI_PICTURE_ASPECT_16_9, false, 0, 0 },
+	{ 32, 1920, 1080,  24, HDMI_PICTURE_ASPECT_16_9, false, 0, 0 },
+	{ 33, 1920, 1080,  25, HDMI_PICTURE_ASPECT_16_9, false, 0, 0 },
+	{ 34, 1920, 1080,  30, HDMI_PICTURE_ASPECT_16_9, false, 0, 0 },
+	{ 35, 2880,  480,  60, HDMI_PICTURE_ASPECT_NONE, false, 0, 3 },
+	{ 37, 2880,  576,  50, HDMI_PICTURE_ASPECT_NONE, false, 0, 3 },
+	{ 39, 1920, 1080,  50, HDMI_PICTURE_ASPECT_16_9, true,  0, 0 },
+	{ 40, 1920, 1080, 100, HDMI_PICTURE_ASPECT_16_9, true,  0, 0 },
+	{ 41, 1280,  720, 100, HDMI_PICTURE_ASPECT_16_9, false, 0, 0 },
+	{ 42,  720,  576, 100, HDMI_PICTURE_ASPECT_NONE, false, 0, 0 },
+	{ 43,  720,  576, 100, HDMI_PICTURE_ASPECT_NONE, false, 0, 0 },
+	{ 44,  720,  576, 100, HDMI_PICTURE_ASPECT_NONE, true,  1, 1 },
+	{ 45,  720,  576, 100, HDMI_PICTURE_ASPECT_NONE, true,  1, 1 },
+	{ 46, 1920, 1080, 120, HDMI_PICTURE_ASPECT_16_9, true,  0, 0 },
+	{ 47, 1280,  720, 120, HDMI_PICTURE_ASPECT_16_9, false, 0, 0 },
+	{ 48,  720,  480, 120, HDMI_PICTURE_ASPECT_NONE, false, 0, 0 },
+	{ 49,  720,  480, 120, HDMI_PICTURE_ASPECT_NONE, false, 0, 0 },
+	{ 50,  720,  480, 120, HDMI_PICTURE_ASPECT_NONE, true,  1, 1 },
+	{ 51,  720,  480, 120, HDMI_PICTURE_ASPECT_NONE, true,  1, 1 },
+	{ 52,  720,  576, 200, HDMI_PICTURE_ASPECT_NONE, false, 0, 0 },
+	{ 53,  720,  576, 200, HDMI_PICTURE_ASPECT_NONE, false, 0, 0 },
+	{ 54,  720,  576, 200, HDMI_PICTURE_ASPECT_NONE, true,  1, 1 },
+	{ 55,  720,  576, 200, HDMI_PICTURE_ASPECT_NONE, true,  1, 1 },
+	{ 56,  720,  480, 240, HDMI_PICTURE_ASPECT_NONE, false, 0, 0 },
+	{ 57,  720,  480, 240, HDMI_PICTURE_ASPECT_NONE, false, 0, 0 },
+	{ 58,  720,  480, 240, HDMI_PICTURE_ASPECT_NONE, true,  1, 1 },
+	{ 59,  720,  480, 240, HDMI_PICTURE_ASPECT_NONE, true,  1, 1 },
+	{ 60, 1280,  720,  24, HDMI_PICTURE_ASPECT_16_9, false, 0, 0 },
+	{ 61, 1280,  720,  25, HDMI_PICTURE_ASPECT_16_9, false, 0, 0 },
+	{ 62, 1280,  720,  30, HDMI_PICTURE_ASPECT_16_9, false, 0, 0 },
+	{ 63, 1920, 1080, 120, HDMI_PICTURE_ASPECT_16_9, false, 0, 0 },
+	{ 64, 1920, 1080, 100, HDMI_PICTURE_ASPECT_16_9, false, 0, 0 },
+};
+
+int drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
+					     struct drm_display_mode *mode)
+{
+	unsigned int i;
+
+	memset(frame, 0, sizeof(*frame));
+
+	frame->type = HDMI_INFOFRAME_TYPE_AVI;
+	frame->version = 2;
+	frame->length = 13;
+
+	for (i = 0; i < ARRAY_SIZE(hdmi_cea_modes); i++) {
+		const struct hdmi_cea_mode *cea = &hdmi_cea_modes[i];
+
+		if (mode->hdisplay != cea->width ||
+		    mode->vdisplay != cea->height)
+			continue;
+
+		if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && !cea->interlaced)
+			continue;
+
+		frame->active_aspect = HDMI_ACTIVE_ASPECT_PICTURE;
+		frame->picture_aspect = cea->aspect;
+		frame->video_code = cea->vic;
+		break;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(drm_hdmi_avi_infoframe_from_display_mode);
diff --git a/include/drm/drm_hdmi.h b/include/drm/drm_hdmi.h
new file mode 100644
index 0000000..07ce049
--- /dev/null
+++ b/include/drm/drm_hdmi.h
@@ -0,0 +1,18 @@ 
+/*
+ * Copyright (C) 2012 Avionic Design GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _DRM_HDMI_H_
+#define _DRM_HDMI_H_
+
+struct hdmi_avi_infoframe;
+struct drm_display_mode;
+
+int drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
+					     struct drm_display_mode *mode);
+
+#endif