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 at 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 --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
-- 
1.8.0

Reply via email to