@@ -3,3 +3,8 @@ menuconfig ADF
depends on SW_SYNC
depends on DMA_SHARED_BUFFER
tristate "Atomic Display Framework"
+
+menuconfig ADF_DISPLAY_CORE
+ depends on ADF
+ depends on DISPLAY_CORE
+ tristate "Helper for implementing ADF interface ops with Display Core devices"
@@ -8,3 +8,5 @@ obj-$(CONFIG_ADF) += adf.o \
adf_sysfs.o
obj-$(CONFIG_COMPAT) += adf_fops32.o
+
+obj-$(CONFIG_ADF_DISPLAY_CORE) += adf_display.o
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2013 Google, Inc.
- * adf_modeinfo_set_name modified from drm_mode_set_name in
+ * adf_modeinfo_{set_name,set_vrefresh} modified from
* drivers/gpu/drm/drm_modes.c
*
* This software is licensed under the terms of the GNU General Public
@@ -966,6 +966,32 @@ void adf_modeinfo_set_name(struct drm_mode_modeinfo *mode)
interlaced ? "i" : "");
}
+void adf_modeinfo_set_vrefresh(struct drm_mode_modeinfo *mode)
+{
+ int refresh = 0;
+ unsigned int calc_val;
+
+ if (mode->vrefresh > 0)
+ return;
+ else if (mode->htotal > 0 && mode->vtotal > 0) {
+ int vtotal;
+ vtotal = mode->vtotal;
+ /* work out vrefresh the value will be x1000 */
+ calc_val = (mode->clock * 1000);
+ calc_val /= mode->htotal;
+ refresh = (calc_val + vtotal / 2) / vtotal;
+
+ if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+ refresh *= 2;
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ refresh /= 2;
+ if (mode->vscan > 1)
+ refresh /= mode->vscan;
+
+ mode->vrefresh = refresh;
+ }
+}
+
static void __exit adf_exit(void);
static int __init adf_init(void)
{
@@ -44,5 +44,6 @@ struct adf_event_refcount *adf_obj_find_refcount(struct adf_obj *obj,
enum adf_event_type type);
void adf_modeinfo_set_name(struct drm_mode_modeinfo *mode);
+void adf_modeinfo_set_vrefresh(struct drm_mode_modeinfo *mode);
#endif /* __ADF_H */
new file mode 100644
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ * adf_modeinfo_from_videomode modified from drm_display_mode_from_videomode in
+ * drivers/gpu/drm/drm_modes.c
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that 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.
+ *
+ */
+
+#include <linux/slab.h>
+#include <video/adf.h>
+#include <video/adf_display.h>
+
+#include "adf.h"
+
+/**
+ * adf_display_entity_screen_size - handle the screen_size interface op
+ * by querying a display core entity
+ */
+int adf_display_entity_screen_size(struct display_entity *display,
+ u16 *width_mm, u16 *height_mm)
+{
+ unsigned int cdf_width, cdf_height;
+ int ret;
+
+ ret = display_entity_get_size(display, &cdf_width, &cdf_height);
+ if (!ret) {
+ *width_mm = cdf_width;
+ *height_mm = cdf_height;
+ }
+ return ret;
+}
+EXPORT_SYMBOL(adf_display_entity_screen_size);
+
+/**
+ * adf_display_entity_notify_connected - notify ADF of a display core entity
+ * being connected to an interface
+ *
+ * @intf: the interface
+ * @display: the display
+ *
+ * adf_display_entity_notify_connected() wraps adf_hotplug_notify_connected()
+ * but does not require a hardware modelist. @display is queried to
+ * automatically populate the modelist.
+ *
+ * Returns 0 on success or error code (<0) on failure.
+ */
+int adf_display_entity_notify_connected(struct adf_interface *intf,
+ struct display_entity *display)
+{
+ const struct videomode *vmodes;
+ struct drm_mode_modeinfo *dmodes = NULL;
+ int ret;
+ size_t i, n_modes;
+
+ ret = display_entity_get_modes(display, &vmodes);
+ if (ret < 0)
+ return ret;
+
+ n_modes = ret;
+ if (n_modes) {
+ dmodes = kzalloc(n_modes * sizeof(dmodes[0]), GFP_KERNEL);
+ if (!dmodes)
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < n_modes; i++)
+ adf_modeinfo_from_videomode(&vmodes[i], &dmodes[i]);
+
+ ret = adf_hotplug_notify_connected(intf, dmodes, n_modes);
+ kfree(dmodes);
+ return ret;
+}
+EXPORT_SYMBOL(adf_display_entity_notify_connected);
+
+/**
+ * adf_modeinfo_from_videomode - copy a display core videomode into
+ * an equivalent &struct drm_mode_modeinfo
+ *
+ * @vm: the input display core videomode
+ * @dmode: the output DRM/ADF modeinfo
+ */
+void adf_modeinfo_from_videomode(const struct videomode *vm,
+ struct drm_mode_modeinfo *dmode)
+{
+ memset(dmode, 0, sizeof(*dmode));
+
+ dmode->hdisplay = vm->hactive;
+ dmode->hsync_start = dmode->hdisplay + vm->hfront_porch;
+ dmode->hsync_end = dmode->hsync_start + vm->hsync_len;
+ dmode->htotal = dmode->hsync_end + vm->hback_porch;
+
+ dmode->vdisplay = vm->vactive;
+ dmode->vsync_start = dmode->vdisplay + vm->vfront_porch;
+ dmode->vsync_end = dmode->vsync_start + vm->vsync_len;
+ dmode->vtotal = dmode->vsync_end + vm->vback_porch;
+
+ dmode->clock = vm->pixelclock / 1000;
+
+ if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH)
+ dmode->flags |= DRM_MODE_FLAG_PHSYNC;
+ else if (vm->flags & DISPLAY_FLAGS_HSYNC_LOW)
+ dmode->flags |= DRM_MODE_FLAG_NHSYNC;
+ if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH)
+ dmode->flags |= DRM_MODE_FLAG_PVSYNC;
+ else if (vm->flags & DISPLAY_FLAGS_VSYNC_LOW)
+ dmode->flags |= DRM_MODE_FLAG_NVSYNC;
+ if (vm->flags & DISPLAY_FLAGS_INTERLACED)
+ dmode->flags |= DRM_MODE_FLAG_INTERLACE;
+ if (vm->flags & DISPLAY_FLAGS_DOUBLESCAN)
+ dmode->flags |= DRM_MODE_FLAG_DBLSCAN;
+
+ adf_modeinfo_set_name(dmode);
+ adf_modeinfo_set_vrefresh(dmode);
+}
+EXPORT_SYMBOL_GPL(adf_modeinfo_from_videomode);
new file mode 100644
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that 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.
+ *
+ */
+
+#ifndef _VIDEO_ADF_DISPLAY_H
+#define _VIDEO_ADF_DISPLAY_H
+
+#include <video/adf.h>
+#include <video/display.h>
+#include <video/videomode.h>
+
+int adf_display_entity_screen_size(struct display_entity *display,
+ u16 *width_mm, u16 *height_mm);
+
+int adf_display_entity_notify_connected(struct adf_interface *intf,
+ struct display_entity *display);
+
+void adf_modeinfo_from_videomode(const struct videomode *vm,
+ struct drm_mode_modeinfo *dmode);
+
+#endif /* _VIDEO_ADF_DISPLAY_H */
Optional helper which implements some ADF interface ops for displays using the Display Core framework Signed-off-by: Greg Hackmann <ghackmann@google.com> --- drivers/video/adf/Kconfig | 5 ++ drivers/video/adf/Makefile | 2 + drivers/video/adf/adf.c | 28 ++++++++- drivers/video/adf/adf.h | 1 + drivers/video/adf/adf_display.c | 123 ++++++++++++++++++++++++++++++++++++++++ include/video/adf_display.h | 31 ++++++++++ 6 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 drivers/video/adf/adf_display.c create mode 100644 include/video/adf_display.h