All of lore.kernel.org
 help / color / mirror / Atom feed
* DRM Display driver for Intel FPGA Video and Image Processing Suite
@ 2017-03-31  9:08 Ong, Hean Loong
  2017-04-02 12:42 ` Daniel Vetter
  2017-04-04  4:01 ` Ong, Hean Loong
  0 siblings, 2 replies; 9+ messages in thread
From: Ong, Hean Loong @ 2017-03-31  9:08 UTC (permalink / raw)
  To: Vetter, Daniel, airlied; +Cc: dri-devel

[-- Attachment #1: Type: text/plain, Size: 755 bytes --]

Hi,

I would like to upstream the attached Intel FPGA Video and Image
Processing Suite. The attached patch supports the Intel Arria10 devkit
and its variants. The purpose of the patch is to enable the FPGA driven
display designed from the Intel Quartus FPGA design suite.

The driver is required as part of the Intel Arria10 devkit reference
design. The driver was tested on:
- The Open Embedded Angstrom Distro. 
- The matchbox-terminal and window-manager was used for functional
testing

Current the intention of the driver is meant to validate the FPGA
designs on the Arria10 devkit for Display Port connecter. We have not
verified its performance of or stability in 3D acceleration or other
non Intel FPGA hardware

BR

Hean Loong

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Intel-FPGA-Video-and-Image-Processing-Suite-Frame-Bu.patch --]
[-- Type: text/x-patch; name="0001-Intel-FPGA-Video-and-Image-Processing-Suite-Frame-Bu.patch", Size: 25434 bytes --]

From 0de293e3646a1780ed603cf8e1f2a19d9aebbe83 Mon Sep 17 00:00:00 2001
From: Ong, Hean Loong <hean.loong.ong@intel.com>
Date: Thu, 30 Mar 2017 18:02:22 +0800
Subject: [PATCHv0] Intel FPGA Video and Image Processing Suite Frame Buffer II driver

Signed-off-by: Ong, Hean Loong <hean.loong.ong@intel.com>
---
 drivers/gpu/drm/Kconfig               |    2 +
 drivers/gpu/drm/Makefile              |    1 +
 drivers/gpu/drm/ivip/Kconfig          |   22 ++++
 drivers/gpu/drm/ivip/Makefile         |    9 ++
 drivers/gpu/drm/ivip/intel_vip_conn.c |  145 ++++++++++++++++++++++
 drivers/gpu/drm/ivip/intel_vip_core.c |  215 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/ivip/intel_vip_crtc.c |  161 ++++++++++++++++++++++++
 drivers/gpu/drm/ivip/intel_vip_drv.h  |   55 +++++++++
 drivers/gpu/drm/ivip/intel_vip_of.c   |  146 ++++++++++++++++++++++
 9 files changed, 756 insertions(+), 0 deletions(-)
 create mode 100644 drivers/gpu/drm/ivip/Kconfig
 create mode 100644 drivers/gpu/drm/ivip/Makefile
 create mode 100644 drivers/gpu/drm/ivip/intel_vip_conn.c
 create mode 100644 drivers/gpu/drm/ivip/intel_vip_core.c
 create mode 100644 drivers/gpu/drm/ivip/intel_vip_crtc.c
 create mode 100644 drivers/gpu/drm/ivip/intel_vip_drv.h
 create mode 100644 drivers/gpu/drm/ivip/intel_vip_of.c

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index ebfe840..c487507 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -167,6 +167,8 @@ source "drivers/gpu/drm/nouveau/Kconfig"
 
 source "drivers/gpu/drm/i915/Kconfig"
 
+source "drivers/gpu/drm/ivip/Kconfig"
+
 config DRM_VGEM
 	tristate "Virtual GEM provider"
 	depends on DRM
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index b9ae428..945cf53 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/
 obj-$(CONFIG_DRM_MGA)	+= mga/
 obj-$(CONFIG_DRM_I810)	+= i810/
 obj-$(CONFIG_DRM_I915)	+= i915/
+obj-$(CONFIG_DRM_IVIP)	+= ivip/
 obj-$(CONFIG_DRM_MGAG200) += mgag200/
 obj-$(CONFIG_DRM_VC4)  += vc4/
 obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus/
diff --git a/drivers/gpu/drm/ivip/Kconfig b/drivers/gpu/drm/ivip/Kconfig
new file mode 100644
index 0000000..ddf3cb5
--- /dev/null
+++ b/drivers/gpu/drm/ivip/Kconfig
@@ -0,0 +1,22 @@
+config DRM_IVIP
+        tristate "Intel FGPA Video and Image Processing"
+        depends on DRM
+        select DRM_GEM_CMA_HELPER
+        select DRM_KMS_HELPER
+        select DRM_KMS_FB_HELPER
+        select DRM_KMS_CMA_HELPER
+        help
+                Choose this option if you have a Intel FPGA Arria 10 system
+                and above with a Display Port IP. This does not support legacy
+                Intel FPGA Cyclone V display port. Currently only single frame
+                buffer is supported. Note that ACPI and X_86 architecture is yet
+                to be supported.
+
+config DRM_IVIP_OF
+        tristate "Intel FGPA Video and Image Processing Open Firmware Systems"
+        depends on DRM_IVIP && OF
+        help
+                Choose this option if the Intel FPGA system is using Open
+                Firmware systems (Arria 10). If M is selected the module would
+                be called ivip.
+
diff --git a/drivers/gpu/drm/ivip/Makefile b/drivers/gpu/drm/ivip/Makefile
new file mode 100644
index 0000000..7be1e99
--- /dev/null
+++ b/drivers/gpu/drm/ivip/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the drm device driver.  This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+
+ccflags-y := -Iinclude/drm
+
+obj-$(CONFIG_DRM_IVIP_OF) += ivip.o
+ivip-objs := intel_vip_of.o intel_vip_core.o \
+intel_vip_conn.o intel_vip_crtc.o
diff --git a/drivers/gpu/drm/ivip/intel_vip_conn.c b/drivers/gpu/drm/ivip/intel_vip_conn.c
new file mode 100644
index 0000000..89ab587
--- /dev/null
+++ b/drivers/gpu/drm/ivip/intel_vip_conn.c
@@ -0,0 +1,145 @@
+/*
+ * intel_vip_conn.c -- Intel Video and Image Processing(VIP)
+ * Frame Buffer II driver
+ *
+ * This driver supports the Intel VIP Frame Reader component.
+ * More info on the hardware can be found in the Intel Video
+ * and Image Processing Suite User Guide at this address
+ * http://www.altera.com/literature/ug/ug_vip.pdf.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * Authors:
+ * Ong, Hean-Loong <hean.loong.ong@intel.com>
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder_slave.h>
+#include <drm/drm_plane_helper.h>
+
+static enum drm_connector_status
+intelvipfb_drm_connector_detect(struct drm_connector *connector, bool force)
+{
+	return connector_status_connected;
+}
+
+static void intelvipfb_drm_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_funcs intelvipfb_drm_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.reset = drm_atomic_helper_connector_reset,
+	.detect = intelvipfb_drm_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = intelvipfb_drm_connector_destroy,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int intelvipfb_drm_connector_get_modes(struct drm_connector *connector)
+{
+	struct drm_device *drm = connector->dev;
+	int count;
+
+	count = drm_add_modes_noedid(connector, drm->mode_config.max_width,
+				     drm->mode_config.max_height);
+	drm_set_preferred_mode(connector, drm->mode_config.max_width,
+			       drm->mode_config.max_height);
+	return count;
+}
+
+static const struct drm_connector_helper_funcs
+intelvipfb_drm_connector_helper_funcs = {
+	.get_modes = intelvipfb_drm_connector_get_modes,
+};
+
+static const struct drm_encoder_funcs
+intelvipfb_drm_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+static void intelvipfb_mode_set(struct drm_encoder *encoder,
+				struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode)
+{
+	/* do nothing */
+}
+
+static void intelvipfb_nop(struct drm_encoder *encoder)
+{
+	/* do nothing */
+}
+
+static const struct drm_encoder_helper_funcs i
+intelvipfb_drm_encoder_helper = {
+	.mode_set = intelvipfb_mode_set,
+	.enable = intelvipfb_nop,
+	.disable = intelvipfb_nop,
+};
+
+int intelvipfb_drm_conn_init(struct drm_device *drm)
+{
+	struct drm_encoder_slave *encoder;
+	struct drm_connector *conn;
+	int ret;
+
+	encoder = devm_kzalloc(drm->dev, sizeof(*encoder), GFP_KERNEL);
+	if (!encoder)
+		return -ENOMEM;
+
+	encoder->base.possible_crtcs = 1;
+	encoder->base.possible_clones = 0;
+
+	ret = drm_encoder_init(drm, &encoder->base,
+			       &intelvipfb_drm_encoder_funcs,
+			       DRM_MODE_ENCODER_VIRTUAL, NULL);
+	if (ret)
+		return ret;
+
+	drm_encoder_helper_add(&encoder->base, &intelvipfb_drm_encoder_helper);
+
+	conn = devm_kzalloc(drm->dev, sizeof(*conn), GFP_KERNEL);
+	if (IS_ERR(conn))
+		return PTR_ERR(conn);
+
+	ret = drm_connector_init(drm, conn, &intelvipfb_drm_connector_funcs,
+				 DRM_MODE_CONNECTOR_DisplayPort);
+	if (ret < 0) {
+		dev_err(drm->dev, "failed to initialize drm connector\n");
+		ret = -ENOMEM;
+		goto error_encoder_cleanup;
+	}
+
+	drm_connector_helper_add(conn, &intelvipfb_drm_connector_helper_funcs);
+
+	ret = drm_mode_connector_attach_encoder(conn, &encoder->base);
+	if (ret < 0) {
+		dev_err(drm->dev, "could not attach connector to encoder\n");
+		drm_connector_unregister(conn);
+		goto error_connector_cleanup;
+	}
+
+	return 0;
+
+error_connector_cleanup:
+	drm_connector_cleanup(conn);
+
+error_encoder_cleanup:
+	drm_encoder_cleanup(&encoder->base);
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/ivip/intel_vip_core.c b/drivers/gpu/drm/ivip/intel_vip_core.c
new file mode 100644
index 0000000..3001ad0
--- /dev/null
+++ b/drivers/gpu/drm/ivip/intel_vip_core.c
@@ -0,0 +1,215 @@
+/*
+ * intel_vip_core.c -- Intel Video and Image Processing(VIP)
+ * Frame Buffer II driver
+ *
+ * This driver supports the Intel VIP Frame Reader component.
+ * More info on the hardware can be found in the Intel Video
+ * and Image Processing Suite User Guide at this address
+ * http://www.altera.com/literature/ug/ug_vip.pdf.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * Authors:
+ * Ong, Hean-Loong <hean.loong.ong@intel.com>
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_of.h>
+
+#include "intel_vip_drv.h"
+
+static const struct file_operations intelvipfb_drm_fops = {
+	.owner		= THIS_MODULE,
+	.open		= drm_open,
+	.release	= drm_release,
+	.unlocked_ioctl	= drm_ioctl,
+	.poll		= drm_poll,
+	.read		= drm_read,
+	.llseek		= no_llseek,
+	.mmap		= drm_gem_cma_mmap,
+};
+
+static void intelvipfb_lastclose(struct drm_device *drm)
+{
+	struct intelvipfb_priv *fbpriv = drm->dev_private;
+
+	drm_fbdev_cma_restore_mode(fbpriv->fbcma);
+}
+
+static struct drm_driver intelvipfb_drm = {
+	.driver_features =
+	    DRIVER_GEM | DRIVER_PRIME |
+	    DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC,
+	.gem_free_object_unlocked = drm_gem_cma_free_object,
+	.gem_vm_ops = &drm_gem_cma_vm_ops,
+	.dumb_create = drm_gem_cma_dumb_create,
+	.dumb_map_offset = drm_gem_cma_dumb_map_offset,
+	.dumb_destroy = drm_gem_dumb_destroy,
+	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+	.gem_prime_export = drm_gem_prime_export,
+	.gem_prime_import = drm_gem_prime_import,
+	.gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
+	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+	.gem_prime_vmap = drm_gem_cma_prime_vmap,
+	.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
+	.gem_prime_mmap = drm_gem_cma_prime_mmap,
+	.name = DRIVER_NAME,
+	.date = "20170329",
+	.desc = "Intel FPGA VIP SUITE",
+	.major = 1,
+	.minor = 0,
+	.patchlevel = 0,
+	.lastclose = intelvipfb_lastclose,
+	.fops = &intelvipfb_drm_fops,
+};
+
+static void intelvipfb_start_hw(void __iomem *base, resource_size_t addr)
+{
+	/*
+	 * The frameinfo variable has to correspond to the size of the VIP Suite
+	 * Frame Reader register 7 which will determine the maximum size used
+	 * in this frameinfo
+	 */
+
+	u32 frameinfo;
+
+	frameinfo =
+		readl(base + INTELVIPFB_FRAME_READER) & 0x00ffffff;
+
+	writel(frameinfo, base + INTELVIPFB_FRAME_INFO);
+
+	writel(addr, base + INTELVIPFB_FRAME_START);
+	/* Finally set the control register to 1 to start streaming */
+	writel(1, base + INTELVIPFB_CONTROL);
+}
+
+static void intelvipfb_disable_hw(void __iomem *base)
+{
+	/* set the control register to 0 to stop streaming */
+	writel(0, base + INTELVIPFB_CONTROL);
+}
+
+static void intelvipfb_output_poll_changed(struct drm_device *drm)
+{
+	struct intelvipfb_priv *fbpriv = drm->dev_private;
+
+	drm_fbdev_cma_hotplug_event(fbpriv->fbcma);
+}
+
+static const struct drm_mode_config_funcs intelvipfb_mode_config_funcs = {
+	.fb_create = drm_fb_cma_create,
+	.output_poll_changed = intelvipfb_output_poll_changed,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = drm_atomic_helper_commit,
+};
+
+static struct drm_mode_config_helper_funcs intelvipfb_mode_config_helpers = {
+	.atomic_commit_tail = drm_atomic_helper_commit_tail,
+};
+
+static void intelvipfb_setup_mode_config(struct drm_device *drm,
+					 struct fb_info *info)
+{
+	drm_mode_config_init(drm);
+	drm->mode_config.min_width = 0;
+	drm->mode_config.min_height = 0;
+	drm->mode_config.max_width = info->var.xres;
+	drm->mode_config.max_height = info->var.yres;
+	drm->mode_config.preferred_depth = 32;
+	drm->mode_config.funcs = &intelvipfb_mode_config_funcs;
+	drm->mode_config.helper_private = &intelvipfb_mode_config_helpers;
+}
+
+int intelvipfb_probe(struct device *dev, void __iomem *base)
+{
+	int retval;
+	struct drm_device *drm;
+	struct intelvipfb_priv *fbpriv = dev_get_drvdata(dev);
+	struct fb_info *info = &fbpriv->info;
+
+	/*setup DRM */
+	drm = drm_dev_alloc(&intelvipfb_drm, dev);
+	if (IS_ERR(drm))
+		return PTR_ERR(drm);
+
+	drm->dev_private = fbpriv;
+
+	dev_set_drvdata(dev, drm);
+
+	intelvipfb_setup_mode_config(drm, info);
+
+	retval = dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32));
+	if (retval)
+		return -ENODEV;
+
+	retval = intelvipfb_setup_crtc(drm);
+	if (retval < 0)
+		return -ENODEV;
+
+	retval = intelvipfb_drm_conn_init(drm);
+	if (retval)
+		return -ENOMEM;
+
+	drm_mode_config_reset(drm);
+
+	fbpriv->fbcma = drm_fbdev_cma_init(drm, PREF_BPP,
+							CRTC_NUM, CONN_NUM);
+	if (!fbpriv->fbcma) {
+		fbpriv->fbcma = NULL;
+		return -ENODEV;
+	}
+
+	intelvipfb_start_hw(base, drm->mode_config.fb_base);
+
+	drm_kms_helper_poll_init(drm);
+
+	drm_dev_register(drm, 0);
+
+	return retval;
+}
+EXPORT_SYMBOL_GPL(intelvipfb_probe);
+
+int intelvipfb_remove(struct device *dev)
+{
+	struct drm_device *drm = dev_get_drvdata(dev);
+	struct intelvipfb_priv *fbpriv = drm->dev_private;
+
+	drm_dev_unregister(drm);
+
+	drm_kms_helper_poll_fini(drm);
+	drm_fbdev_cma_fini(fbpriv->fbcma);
+
+	intelvipfb_disable_hw(fbpriv->base);
+
+drm_mode_config_cleanup(drm);
+
+drm_dev_unref(drm);
+
+devm_kfree(dev, fbpriv);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(intelvipfb_remove);
+
+MODULE_AUTHOR("Ong, Hean-Loong <hean.loong.ong@intel.com>");
+MODULE_DESCRIPTION("Intel VIP Frame Buffer II driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/ivip/intel_vip_crtc.c b/drivers/gpu/drm/ivip/intel_vip_crtc.c
new file mode 100644
index 0000000..97a3954
--- /dev/null
+++ b/drivers/gpu/drm/ivip/intel_vip_crtc.c
@@ -0,0 +1,161 @@
+/*
+ * intel_vip_crtc.c -- Intel Video and Image Processing(VIP)
+ * Frame Buffer II driver
+ *
+ * This driver supports the Intel VIP Frame Reader component.
+ * More info on the hardware can be found in the Intel Video
+ * and Image Processing Suite User Guide at this address
+ * http://www.altera.com/literature/ug/ug_vip.pdf.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * Authors:
+ * Ong, Hean-Loong <hean.loong.ong@intel.com>
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_data/simplefb.h>
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_plane_helper.h>
+
+#include "intel_vip_drv.h"
+
+static struct simplefb_format intelvipfb_formats[] = SIMPLEFB_FORMATS;
+
+static void intelvipfb_crtc_destroy(struct drm_crtc *crtc)
+{
+	drm_crtc_cleanup(crtc);
+	kfree(crtc);
+}
+
+static const struct drm_crtc_funcs intelvipfb_crtc_funcs = {
+	.destroy = intelvipfb_crtc_destroy,
+	.set_config = drm_atomic_helper_set_config,
+	.page_flip = drm_atomic_helper_page_flip,
+	.reset = drm_atomic_helper_crtc_reset,
+	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+};
+
+static void intelvipfb_crtc_atomic_begin(struct drm_crtc *crtc,
+					 struct drm_crtc_state *state)
+{
+	struct drm_pending_vblank_event *event = crtc->state->event;
+
+	if (event) {
+		crtc->state->event = NULL;
+
+		spin_lock_irq(&crtc->dev->event_lock);
+		drm_crtc_send_vblank_event(crtc, event);
+		spin_unlock_irq(&crtc->dev->event_lock);
+	}
+}
+
+static void intelvipfb_crtc_nop(struct drm_crtc *crtc)
+{
+	/* do nothing */;
+}
+
+static const struct drm_crtc_helper_funcs intelvipfb_crtc_helper_funcs = {
+	.atomic_begin	= intelvipfb_crtc_atomic_begin,
+	.enable = intelvipfb_crtc_nop,
+};
+
+static void intelvipfb_plane_destroy(struct drm_plane *plane)
+{
+	drm_plane_helper_disable(plane);
+	drm_plane_cleanup(plane);
+}
+
+static const struct drm_plane_funcs intelvipfb_plane_funcs = {
+	.update_plane		= drm_atomic_helper_update_plane,
+	.disable_plane		= drm_atomic_helper_disable_plane,
+	.destroy		= intelvipfb_plane_destroy,
+	.reset			= drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
+};
+
+static void intelvipfb_plane_atomic_update(struct drm_plane *plane,
+					   struct drm_plane_state *state)
+{
+	struct intelvipfb_priv *fbpriv;
+	struct drm_gem_cma_object *gem;
+
+	if (!plane->state->crtc || !plane->state->fb)
+		return;
+
+	fbpriv = plane->dev->dev_private;
+	gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
+	writel(gem->paddr, fbpriv->base + INTELVIPFB_FRAME_START);
+}
+
+static const struct drm_plane_helper_funcs intelvipfb_plane_helper_funcs = {
+	.atomic_update = intelvipfb_plane_atomic_update,
+};
+
+static struct drm_plane *intelvipfb_plane_init(struct drm_device *drm)
+{
+	struct drm_plane *plane = NULL;
+	u32 formats[ARRAY_SIZE(intelvipfb_formats)], i;
+	int ret;
+
+	plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
+	if (!plane)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < ARRAY_SIZE(intelvipfb_formats); i++)
+		formats[i] = intelvipfb_formats[i].fourcc;
+
+	ret = drm_universal_plane_init(drm, plane, 0xff,
+				       &intelvipfb_plane_funcs,
+				       formats, ARRAY_SIZE(formats),
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret)
+		return ERR_PTR(ret);
+
+	drm_plane_helper_add(plane, &intelvipfb_plane_helper_funcs);
+
+	return plane;
+}
+
+int intelvipfb_setup_crtc(struct drm_device *drm)
+{
+	struct drm_crtc *crtc;
+	struct drm_plane *primary;
+	int ret;
+
+	crtc = kzalloc(sizeof(*crtc), GFP_KERNEL);
+	if (!crtc)
+		return -ENOMEM;
+
+	primary = intelvipfb_plane_init(drm);
+	if (IS_ERR(primary))
+		return PTR_ERR(primary);
+
+	ret = drm_crtc_init_with_planes(drm, crtc, primary, NULL,
+					&intelvipfb_crtc_funcs, NULL);
+
+	if (ret) {
+		intelvipfb_plane_destroy(primary);
+		return ret;
+	}
+
+	drm_crtc_helper_add(crtc, &intelvipfb_crtc_helper_funcs);
+	return 0;
+}
diff --git a/drivers/gpu/drm/ivip/intel_vip_drv.h b/drivers/gpu/drm/ivip/intel_vip_drv.h
new file mode 100644
index 0000000..657f23c
--- /dev/null
+++ b/drivers/gpu/drm/ivip/intel_vip_drv.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2017 Intel Corporation.
+ *
+ * Intel Video and Image Processing(VIP) Frame Buffer II driver.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Ong, Hean-Loong <hean.loong.ong@intel.com>
+ *
+ */
+#ifndef _INTEL_VIP_DRV_H
+#define _INTEL_VIP_DRV_H
+#include <linux/io.h>
+#include <linux/fb.h>
+
+#define DRIVER_NAME	"intelvipfb"
+#define BYTES_PER_PIXEL	4
+#define PREF_BPP		32
+#define CRTC_NUM		1
+#define CONN_NUM		1
+
+/* control registers */
+#define INTELVIPFB_CONTROL		0
+#define INTELVIPFB_STATUS		0x4
+#define INTELVIPFB_INTERRUPT		0x8
+#define INTELVIPFB_FRAME_COUNTER	0xC
+#define INTELVIPFB_FRAME_DROP		0x10
+#define INTELVIPFB_FRAME_INFO		0x14
+#define INTELVIPFB_FRAME_START		0x18
+#define INTELVIPFB_FRAME_READER		0x1C
+
+int intelvipfb_probe(struct device *dev, void __iomem *base);
+int intelvipfb_remove(struct device *dev);
+int intelvipfb_setup_crtc(struct drm_device *drm);
+int intelvipfb_drm_conn_init(struct drm_device *drm);
+
+struct intelvipfb_priv {
+	struct drm_fbdev_cma *fbcma;
+	struct drm_device *drm;
+	struct fb_info info;
+	void	__iomem		*base;
+};
+
+#endif
diff --git a/drivers/gpu/drm/ivip/intel_vip_of.c b/drivers/gpu/drm/ivip/intel_vip_of.c
new file mode 100644
index 0000000..17dff36
--- /dev/null
+++ b/drivers/gpu/drm/ivip/intel_vip_of.c
@@ -0,0 +1,146 @@
+/*
+ * intel_vip_of.c -- Intel Video and Image Processing(VIP)
+ * Frame Buffer II driver
+ *
+ * This driver supports the Intel VIP Frame Reader component.
+ * More info on the hardware can be found in the Intel Video
+ * and Image Processing Suite User Guide at this address
+ * http://www.altera.com/literature/ug/ug_vip.pdf.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * Authors:
+ * Ong, Hean-Loong <hean.loong.ong@intel.com>
+ *
+ */
+
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <drm/drm_fb_helper.h>
+#include "intel_vip_drv.h"
+
+/*
+ * Setting up information derived from OF Device Tree Nodes
+ * max-width, max-height, bits per pixel, memory port width
+ */
+
+static int intelvipfb_of_setup(struct intelvipfb_priv *fbdata,
+			       struct platform_device *pdev)
+{
+	int ret;
+	int mem_word_width;
+	u32 bits_per_color;
+	struct device_node *np = pdev->dev.of_node;
+
+	ret = of_property_read_u32(np, "altr,max-width",
+				   &fbdata->info.var.xres);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Missing required parameter 'altr,max-width'");
+		return ret;
+	}
+	fbdata->info.var.xres_virtual = fbdata->info.var.xres;
+
+	ret = of_property_read_u32(np, "altr,max-height",
+				   &fbdata->info.var.yres);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Missing required parameter 'altr,max-height'");
+		return ret;
+	}
+	fbdata->info.var.yres_virtual = fbdata->info.var.yres;
+
+	ret = of_property_read_u32(np, "altr,bits-per-symbol", &bits_per_color);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Missing required parameter 'altr,bits-per-symbol'");
+		return ret;
+	}
+
+	fbdata->info.var.bits_per_pixel = bits_per_color * BYTES_PER_PIXEL;
+
+	ret = of_property_read_u32(np, "altr,mem-port-width", &mem_word_width);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Missing required parameter 'altr,mem-port-width '");
+		return ret;
+	}
+
+	if (!(mem_word_width >= 32 && mem_word_width % 32 == 0)) {
+		dev_err(&pdev->dev,
+			"mem-word-width is set to %i. must be >= 32 and multiple of 32.",
+			 mem_word_width);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int intelvipfb_of_probe(struct platform_device *pdev)
+{
+	int retval;
+	struct resource *reg_res;
+	struct intelvipfb_priv *fbdata;
+
+	fbdata = devm_kzalloc(&pdev->dev, sizeof(*fbdata), GFP_KERNEL);
+	if (!fbdata)
+		return -ENOMEM;
+
+	reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!reg_res)
+		return -ENOMEM;
+
+	fbdata->base = devm_ioremap_resource(&pdev->dev, reg_res);
+
+	if (IS_ERR(fbdata->base)) {
+		dev_err(&pdev->dev, "devm_ioremap_resource failed\n");
+		retval = PTR_ERR(fbdata->base);
+		return -ENOMEM;
+	}
+
+	intelvipfb_of_setup(fbdata, pdev);
+
+	platform_set_drvdata(pdev, fbdata);
+
+	return intelvipfb_probe(&pdev->dev, fbdata->base);
+}
+
+static int intelvipfb_of_remove(struct platform_device *pdev)
+{
+	return intelvipfb_remove(&pdev->dev);
+}
+
+/*
+ * The name vip-frame-buffer-2.0 is derived from
+ * http://www.altera.com/literature/ug/ug_vip.pdf
+ * frame buffer IP cores section 14
+ */
+
+static const struct of_device_id intelvipfb_of_match[] = {
+	{ .compatible = "altr,vip-frame-buffer-2.0" },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, intelvipfb_of_match);
+
+static struct platform_driver intelvipfb_driver = {
+	.probe = intelvipfb_of_probe,
+	.remove = intelvipfb_of_remove,
+	.driver = {
+		.name = DRIVER_NAME,
+		.of_match_table = intelvipfb_of_match,
+	},
+};
+
+module_platform_driver(intelvipfb_driver);
-- 
1.7.1


[-- Attachment #3: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: DRM Display driver for Intel FPGA Video and Image Processing Suite
  2017-03-31  9:08 DRM Display driver for Intel FPGA Video and Image Processing Suite Ong, Hean Loong
@ 2017-04-02 12:42 ` Daniel Vetter
  2017-04-04  4:01 ` Ong, Hean Loong
  1 sibling, 0 replies; 9+ messages in thread
From: Daniel Vetter @ 2017-04-02 12:42 UTC (permalink / raw)
  To: Ong, Hean Loong; +Cc: Vetter, Daniel, dri-devel

On Fri, Mar 31, 2017 at 09:08:37AM +0000, Ong, Hean Loong wrote:
> Hi,
> 
> I would like to upstream the attached Intel FPGA Video and Image
> Processing Suite. The attached patch supports the Intel Arria10 devkit
> and its variants. The purpose of the patch is to enable the FPGA driven
> display designed from the Intel Quartus FPGA design suite.

For my understanding of the hw: Does this fpga thing have a real output,
or is it a virtual thing? It kinda looks very much like a virtual output
...

> The driver is required as part of the Intel Arria10 devkit reference
> design. The driver was tested on:
> - The Open Embedded Angstrom Distro. 
> - The matchbox-terminal and window-manager was used for functional
> testing

Please use igt to validate your driver, running a desktop isn't really a
full work-out. See https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#testing-and-validation
> 
> Current the intention of the driver is meant to validate the FPGA
> designs on the Arria10 devkit for Display Port connecter. We have not
> verified its performance of or stability in 3D acceleration or other
> non Intel FPGA hardware

For next time around, pls submit is plain patch, not attached. You might
need to ask intel IT to adjust your outlook setttings to make sure it goes
through. Bunch of comments below.

Also, do you want to maintain this as part of the "small drivers in
drm-misc" effort? See:

https://01.org/linuxgraphics/gfx-docs/maintainer-tools/drm-misc.html#small-drivers

Note that it's no longer an expirement, we're accepting new drivers (but
the patch to change that hasn't gone through the autobuilders yet, hence
docs are a bit stale).

Bunch of comments below. Overall looks like a nice simple&clean driver.

Cheers, Daniel

> 
> BR
> 
> Hean Loong

> From 0de293e3646a1780ed603cf8e1f2a19d9aebbe83 Mon Sep 17 00:00:00 2001
> From: Ong, Hean Loong <hean.loong.ong@intel.com>
> Date: Thu, 30 Mar 2017 18:02:22 +0800
> Subject: [PATCHv0] Intel FPGA Video and Image Processing Suite Frame Buffer II driver
> 
> Signed-off-by: Ong, Hean Loong <hean.loong.ong@intel.com>
> ---
>  drivers/gpu/drm/Kconfig               |    2 +
>  drivers/gpu/drm/Makefile              |    1 +
>  drivers/gpu/drm/ivip/Kconfig          |   22 ++++
>  drivers/gpu/drm/ivip/Makefile         |    9 ++
>  drivers/gpu/drm/ivip/intel_vip_conn.c |  145 ++++++++++++++++++++++
>  drivers/gpu/drm/ivip/intel_vip_core.c |  215 +++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/ivip/intel_vip_crtc.c |  161 ++++++++++++++++++++++++
>  drivers/gpu/drm/ivip/intel_vip_drv.h  |   55 +++++++++
>  drivers/gpu/drm/ivip/intel_vip_of.c   |  146 ++++++++++++++++++++++
>  9 files changed, 756 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/gpu/drm/ivip/Kconfig
>  create mode 100644 drivers/gpu/drm/ivip/Makefile
>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_conn.c
>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_core.c
>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_crtc.c
>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_drv.h
>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_of.c
> 
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index ebfe840..c487507 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
> @@ -167,6 +167,8 @@ source "drivers/gpu/drm/nouveau/Kconfig"
>  
>  source "drivers/gpu/drm/i915/Kconfig"
>  
> +source "drivers/gpu/drm/ivip/Kconfig"
> +
>  config DRM_VGEM
>  	tristate "Virtual GEM provider"
>  	depends on DRM
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index b9ae428..945cf53 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -52,6 +52,7 @@ obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/
>  obj-$(CONFIG_DRM_MGA)	+= mga/
>  obj-$(CONFIG_DRM_I810)	+= i810/
>  obj-$(CONFIG_DRM_I915)	+= i915/
> +obj-$(CONFIG_DRM_IVIP)	+= ivip/
>  obj-$(CONFIG_DRM_MGAG200) += mgag200/
>  obj-$(CONFIG_DRM_VC4)  += vc4/
>  obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus/
> diff --git a/drivers/gpu/drm/ivip/Kconfig b/drivers/gpu/drm/ivip/Kconfig
> new file mode 100644
> index 0000000..ddf3cb5
> --- /dev/null
> +++ b/drivers/gpu/drm/ivip/Kconfig
> @@ -0,0 +1,22 @@
> +config DRM_IVIP
> +        tristate "Intel FGPA Video and Image Processing"
> +        depends on DRM
> +        select DRM_GEM_CMA_HELPER
> +        select DRM_KMS_HELPER
> +        select DRM_KMS_FB_HELPER
> +        select DRM_KMS_CMA_HELPER
> +        help
> +                Choose this option if you have a Intel FPGA Arria 10 system
> +                and above with a Display Port IP. This does not support legacy
> +                Intel FPGA Cyclone V display port. Currently only single frame
> +                buffer is supported. Note that ACPI and X_86 architecture is yet
> +                to be supported.

This config option seems defunct, only IVIP_OF seems to do anything.
Please merge.

> +
> +config DRM_IVIP_OF
> +        tristate "Intel FGPA Video and Image Processing Open Firmware Systems"
> +        depends on DRM_IVIP && OF
> +        help
> +                Choose this option if the Intel FPGA system is using Open
> +                Firmware systems (Arria 10). If M is selected the module would
> +                be called ivip.
> +
> diff --git a/drivers/gpu/drm/ivip/Makefile b/drivers/gpu/drm/ivip/Makefile
> new file mode 100644
> index 0000000..7be1e99
> --- /dev/null
> +++ b/drivers/gpu/drm/ivip/Makefile
> @@ -0,0 +1,9 @@
> +#
> +# Makefile for the drm device driver.  This driver provides support for the
> +# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
> +
> +ccflags-y := -Iinclude/drm
> +
> +obj-$(CONFIG_DRM_IVIP_OF) += ivip.o
> +ivip-objs := intel_vip_of.o intel_vip_core.o \
> +intel_vip_conn.o intel_vip_crtc.o
> diff --git a/drivers/gpu/drm/ivip/intel_vip_conn.c b/drivers/gpu/drm/ivip/intel_vip_conn.c
> new file mode 100644
> index 0000000..89ab587
> --- /dev/null
> +++ b/drivers/gpu/drm/ivip/intel_vip_conn.c
> @@ -0,0 +1,145 @@
> +/*
> + * intel_vip_conn.c -- Intel Video and Image Processing(VIP)
> + * Frame Buffer II driver
> + *
> + * This driver supports the Intel VIP Frame Reader component.
> + * More info on the hardware can be found in the Intel Video
> + * and Image Processing Suite User Guide at this address
> + * http://www.altera.com/literature/ug/ug_vip.pdf.
> + *
> + * 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.
> + *
> + * 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.
> + *
> + * Authors:
> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
> + *
> + */
> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder_slave.h>
> +#include <drm/drm_plane_helper.h>
> +
> +static enum drm_connector_status
> +intelvipfb_drm_connector_detect(struct drm_connector *connector, bool force)
> +{
> +	return connector_status_connected;
> +}
> +
> +static void intelvipfb_drm_connector_destroy(struct drm_connector *connector)
> +{
> +	drm_connector_unregister(connector);
> +	drm_connector_cleanup(connector);
> +}
> +
> +static const struct drm_connector_funcs intelvipfb_drm_connector_funcs = {
> +	.dpms = drm_helper_connector_dpms,
> +	.reset = drm_atomic_helper_connector_reset,
> +	.detect = intelvipfb_drm_connector_detect,
> +	.fill_modes = drm_helper_probe_single_connector_modes,
> +	.destroy = intelvipfb_drm_connector_destroy,
> +	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static int intelvipfb_drm_connector_get_modes(struct drm_connector *connector)
> +{
> +	struct drm_device *drm = connector->dev;
> +	int count;
> +
> +	count = drm_add_modes_noedid(connector, drm->mode_config.max_width,
> +				     drm->mode_config.max_height);
> +	drm_set_preferred_mode(connector, drm->mode_config.max_width,
> +			       drm->mode_config.max_height);
> +	return count;
> +}
> +
> +static const struct drm_connector_helper_funcs
> +intelvipfb_drm_connector_helper_funcs = {
> +	.get_modes = intelvipfb_drm_connector_get_modes,
> +};
> +
> +static const struct drm_encoder_funcs
> +intelvipfb_drm_encoder_funcs = {
> +	.destroy = drm_encoder_cleanup,
> +};

It'd be great to extract a virtual_connector helper which just provides
one default mode and could be used by all virtual drivers ... Just a
thought to look into, can of course be done as a follow-up.

> +
> +static void intelvipfb_mode_set(struct drm_encoder *encoder,
> +				struct drm_display_mode *mode,
> +				struct drm_display_mode *adjusted_mode)
> +{
> +	/* do nothing */
> +}
> +
> +static void intelvipfb_nop(struct drm_encoder *encoder)
> +{
> +	/* do nothing */
> +}

Please drop these dummy functions, they're not needed on latest kernels.

> +
> +static const struct drm_encoder_helper_funcs i
> +intelvipfb_drm_encoder_helper = {
> +	.mode_set = intelvipfb_mode_set,
> +	.enable = intelvipfb_nop,
> +	.disable = intelvipfb_nop,
> +};
> +
> +int intelvipfb_drm_conn_init(struct drm_device *drm)
> +{
> +	struct drm_encoder_slave *encoder;
> +	struct drm_connector *conn;
> +	int ret;
> +
> +	encoder = devm_kzalloc(drm->dev, sizeof(*encoder), GFP_KERNEL);
> +	if (!encoder)
> +		return -ENOMEM;
> +
> +	encoder->base.possible_crtcs = 1;
> +	encoder->base.possible_clones = 0;
> +
> +	ret = drm_encoder_init(drm, &encoder->base,
> +			       &intelvipfb_drm_encoder_funcs,
> +			       DRM_MODE_ENCODER_VIRTUAL, NULL);
> +	if (ret)
> +		return ret;
> +
> +	drm_encoder_helper_add(&encoder->base, &intelvipfb_drm_encoder_helper);
> +
> +	conn = devm_kzalloc(drm->dev, sizeof(*conn), GFP_KERNEL);
> +	if (IS_ERR(conn))
> +		return PTR_ERR(conn);
> +
> +	ret = drm_connector_init(drm, conn, &intelvipfb_drm_connector_funcs,
> +				 DRM_MODE_CONNECTOR_DisplayPort);
> +	if (ret < 0) {
> +		dev_err(drm->dev, "failed to initialize drm connector\n");
> +		ret = -ENOMEM;
> +		goto error_encoder_cleanup;
> +	}
> +
> +	drm_connector_helper_add(conn, &intelvipfb_drm_connector_helper_funcs);
> +
> +	ret = drm_mode_connector_attach_encoder(conn, &encoder->base);
> +	if (ret < 0) {
> +		dev_err(drm->dev, "could not attach connector to encoder\n");
> +		drm_connector_unregister(conn);
> +		goto error_connector_cleanup;
> +	}
> +
> +	return 0;
> +
> +error_connector_cleanup:
> +	drm_connector_cleanup(conn);
> +
> +error_encoder_cleanup:
> +	drm_encoder_cleanup(&encoder->base);
> +
> +	return ret;
> +}
> diff --git a/drivers/gpu/drm/ivip/intel_vip_core.c b/drivers/gpu/drm/ivip/intel_vip_core.c
> new file mode 100644
> index 0000000..3001ad0
> --- /dev/null
> +++ b/drivers/gpu/drm/ivip/intel_vip_core.c
> @@ -0,0 +1,215 @@
> +/*
> + * intel_vip_core.c -- Intel Video and Image Processing(VIP)
> + * Frame Buffer II driver
> + *
> + * This driver supports the Intel VIP Frame Reader component.
> + * More info on the hardware can be found in the Intel Video
> + * and Image Processing Suite User Guide at this address
> + * http://www.altera.com/literature/ug/ug_vip.pdf.
> + *
> + * 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.
> + *
> + * 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.
> + *
> + * Authors:
> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
> + *
> + */
> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_of.h>
> +
> +#include "intel_vip_drv.h"
> +
> +static const struct file_operations intelvipfb_drm_fops = {
> +	.owner		= THIS_MODULE,
> +	.open		= drm_open,
> +	.release	= drm_release,
> +	.unlocked_ioctl	= drm_ioctl,
> +	.poll		= drm_poll,
> +	.read		= drm_read,
> +	.llseek		= no_llseek,
> +	.mmap		= drm_gem_cma_mmap,

Please use the shiny new DRM_GEM_CMA_FOPS macro merged into linux-next
just recently.

> +};
> +
> +static void intelvipfb_lastclose(struct drm_device *drm)
> +{
> +	struct intelvipfb_priv *fbpriv = drm->dev_private;
> +
> +	drm_fbdev_cma_restore_mode(fbpriv->fbcma);
> +}
> +
> +static struct drm_driver intelvipfb_drm = {
> +	.driver_features =
> +	    DRIVER_GEM | DRIVER_PRIME |
> +	    DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC,
> +	.gem_free_object_unlocked = drm_gem_cma_free_object,
> +	.gem_vm_ops = &drm_gem_cma_vm_ops,
> +	.dumb_create = drm_gem_cma_dumb_create,
> +	.dumb_map_offset = drm_gem_cma_dumb_map_offset,
> +	.dumb_destroy = drm_gem_dumb_destroy,
> +	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
> +	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
> +	.gem_prime_export = drm_gem_prime_export,
> +	.gem_prime_import = drm_gem_prime_import,
> +	.gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
> +	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
> +	.gem_prime_vmap = drm_gem_cma_prime_vmap,
> +	.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
> +	.gem_prime_mmap = drm_gem_cma_prime_mmap,
> +	.name = DRIVER_NAME,
> +	.date = "20170329",
> +	.desc = "Intel FPGA VIP SUITE",
> +	.major = 1,
> +	.minor = 0,
> +	.patchlevel = 0,
> +	.lastclose = intelvipfb_lastclose,
> +	.fops = &intelvipfb_drm_fops,
> +};
> +
> +static void intelvipfb_start_hw(void __iomem *base, resource_size_t addr)
> +{
> +	/*
> +	 * The frameinfo variable has to correspond to the size of the VIP Suite
> +	 * Frame Reader register 7 which will determine the maximum size used
> +	 * in this frameinfo
> +	 */
> +
> +	u32 frameinfo;
> +
> +	frameinfo =
> +		readl(base + INTELVIPFB_FRAME_READER) & 0x00ffffff;
> +
> +	writel(frameinfo, base + INTELVIPFB_FRAME_INFO);
> +
> +	writel(addr, base + INTELVIPFB_FRAME_START);
> +	/* Finally set the control register to 1 to start streaming */
> +	writel(1, base + INTELVIPFB_CONTROL);
> +}
> +
> +static void intelvipfb_disable_hw(void __iomem *base)
> +{
> +	/* set the control register to 0 to stop streaming */
> +	writel(0, base + INTELVIPFB_CONTROL);
> +}
> +
> +static void intelvipfb_output_poll_changed(struct drm_device *drm)
> +{
> +	struct intelvipfb_priv *fbpriv = drm->dev_private;
> +
> +	drm_fbdev_cma_hotplug_event(fbpriv->fbcma);
> +}
> +
> +static const struct drm_mode_config_funcs intelvipfb_mode_config_funcs = {
> +	.fb_create = drm_fb_cma_create,
> +	.output_poll_changed = intelvipfb_output_poll_changed,
> +	.atomic_check = drm_atomic_helper_check,
> +	.atomic_commit = drm_atomic_helper_commit,
> +};
> +
> +static struct drm_mode_config_helper_funcs intelvipfb_mode_config_helpers = {
> +	.atomic_commit_tail = drm_atomic_helper_commit_tail,
> +};
> +
> +static void intelvipfb_setup_mode_config(struct drm_device *drm,
> +					 struct fb_info *info)
> +{
> +	drm_mode_config_init(drm);
> +	drm->mode_config.min_width = 0;
> +	drm->mode_config.min_height = 0;
> +	drm->mode_config.max_width = info->var.xres;
> +	drm->mode_config.max_height = info->var.yres;
> +	drm->mode_config.preferred_depth = 32;
> +	drm->mode_config.funcs = &intelvipfb_mode_config_funcs;
> +	drm->mode_config.helper_private = &intelvipfb_mode_config_helpers;
> +}
> +
> +int intelvipfb_probe(struct device *dev, void __iomem *base)
> +{
> +	int retval;
> +	struct drm_device *drm;
> +	struct intelvipfb_priv *fbpriv = dev_get_drvdata(dev);
> +	struct fb_info *info = &fbpriv->info;
> +
> +	/*setup DRM */
> +	drm = drm_dev_alloc(&intelvipfb_drm, dev);
> +	if (IS_ERR(drm))
> +		return PTR_ERR(drm);
> +
> +	drm->dev_private = fbpriv;
> +
> +	dev_set_drvdata(dev, drm);
> +
> +	intelvipfb_setup_mode_config(drm, info);
> +
> +	retval = dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32));
> +	if (retval)
> +		return -ENODEV;
> +
> +	retval = intelvipfb_setup_crtc(drm);
> +	if (retval < 0)
> +		return -ENODEV;
> +
> +	retval = intelvipfb_drm_conn_init(drm);
> +	if (retval)
> +		return -ENOMEM;
> +
> +	drm_mode_config_reset(drm);
> +
> +	fbpriv->fbcma = drm_fbdev_cma_init(drm, PREF_BPP,
> +							CRTC_NUM, CONN_NUM);
> +	if (!fbpriv->fbcma) {
> +		fbpriv->fbcma = NULL;
> +		return -ENODEV;
> +	}
> +
> +	intelvipfb_start_hw(base, drm->mode_config.fb_base);
> +
> +	drm_kms_helper_poll_init(drm);
> +
> +	drm_dev_register(drm, 0);
> +
> +	return retval;
> +}
> +EXPORT_SYMBOL_GPL(intelvipfb_probe);
> +
> +int intelvipfb_remove(struct device *dev)
> +{
> +	struct drm_device *drm = dev_get_drvdata(dev);
> +	struct intelvipfb_priv *fbpriv = drm->dev_private;
> +
> +	drm_dev_unregister(drm);
> +
> +	drm_kms_helper_poll_fini(drm);
> +	drm_fbdev_cma_fini(fbpriv->fbcma);
> +
> +	intelvipfb_disable_hw(fbpriv->base);
> +
> +drm_mode_config_cleanup(drm);
> +
> +drm_dev_unref(drm);
> +
> +devm_kfree(dev, fbpriv);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(intelvipfb_remove);
> +
> +MODULE_AUTHOR("Ong, Hean-Loong <hean.loong.ong@intel.com>");
> +MODULE_DESCRIPTION("Intel VIP Frame Buffer II driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/gpu/drm/ivip/intel_vip_crtc.c b/drivers/gpu/drm/ivip/intel_vip_crtc.c
> new file mode 100644
> index 0000000..97a3954
> --- /dev/null
> +++ b/drivers/gpu/drm/ivip/intel_vip_crtc.c
> @@ -0,0 +1,161 @@
> +/*
> + * intel_vip_crtc.c -- Intel Video and Image Processing(VIP)
> + * Frame Buffer II driver
> + *
> + * This driver supports the Intel VIP Frame Reader component.
> + * More info on the hardware can be found in the Intel Video
> + * and Image Processing Suite User Guide at this address
> + * http://www.altera.com/literature/ug/ug_vip.pdf.
> + *
> + * 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.
> + *
> + * 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.
> + *
> + * Authors:
> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
> + *
> + */
> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/platform_data/simplefb.h>
> +
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_plane_helper.h>
> +
> +#include "intel_vip_drv.h"
> +
> +static struct simplefb_format intelvipfb_formats[] = SIMPLEFB_FORMATS;

This looks like copypasta from simplefb? Please remove.

> +
> +static void intelvipfb_crtc_destroy(struct drm_crtc *crtc)
> +{
> +	drm_crtc_cleanup(crtc);
> +	kfree(crtc);
> +}
> +
> +static const struct drm_crtc_funcs intelvipfb_crtc_funcs = {
> +	.destroy = intelvipfb_crtc_destroy,
> +	.set_config = drm_atomic_helper_set_config,
> +	.page_flip = drm_atomic_helper_page_flip,
> +	.reset = drm_atomic_helper_crtc_reset,
> +	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
> +};
> +
> +static void intelvipfb_crtc_atomic_begin(struct drm_crtc *crtc,
> +					 struct drm_crtc_state *state)
> +{
> +	struct drm_pending_vblank_event *event = crtc->state->event;
> +
> +	if (event) {
> +		crtc->state->event = NULL;
> +
> +		spin_lock_irq(&crtc->dev->event_lock);
> +		drm_crtc_send_vblank_event(crtc, event);
> +		spin_unlock_irq(&crtc->dev->event_lock);
> +	}
> +}
> +
> +static void intelvipfb_crtc_nop(struct drm_crtc *crtc)
> +{
> +	/* do nothing */;
> +}

Again, don't fill out no-ops.

> +
> +static const struct drm_crtc_helper_funcs intelvipfb_crtc_helper_funcs = {
> +	.atomic_begin	= intelvipfb_crtc_atomic_begin,
> +	.enable = intelvipfb_crtc_nop,
> +};
> +
> +static void intelvipfb_plane_destroy(struct drm_plane *plane)
> +{
> +	drm_plane_helper_disable(plane);
> +	drm_plane_cleanup(plane);
> +}
> +
> +static const struct drm_plane_funcs intelvipfb_plane_funcs = {
> +	.update_plane		= drm_atomic_helper_update_plane,
> +	.disable_plane		= drm_atomic_helper_disable_plane,
> +	.destroy		= intelvipfb_plane_destroy,
> +	.reset			= drm_atomic_helper_plane_reset,
> +	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> +	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
> +};
> +
> +static void intelvipfb_plane_atomic_update(struct drm_plane *plane,
> +					   struct drm_plane_state *state)
> +{
> +	struct intelvipfb_priv *fbpriv;
> +	struct drm_gem_cma_object *gem;
> +
> +	if (!plane->state->crtc || !plane->state->fb)
> +		return;
> +
> +	fbpriv = plane->dev->dev_private;
> +	gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
> +	writel(gem->paddr, fbpriv->base + INTELVIPFB_FRAME_START);
> +}
> +
> +static const struct drm_plane_helper_funcs intelvipfb_plane_helper_funcs = {
> +	.atomic_update = intelvipfb_plane_atomic_update,
> +};
> +
> +static struct drm_plane *intelvipfb_plane_init(struct drm_device *drm)
> +{
> +	struct drm_plane *plane = NULL;
> +	u32 formats[ARRAY_SIZE(intelvipfb_formats)], i;
> +	int ret;
> +
> +	plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
> +	if (!plane)
> +		return ERR_PTR(-ENOMEM);
> +
> +	for (i = 0; i < ARRAY_SIZE(intelvipfb_formats); i++)
> +		formats[i] = intelvipfb_formats[i].fourcc;
> +
> +	ret = drm_universal_plane_init(drm, plane, 0xff,
> +				       &intelvipfb_plane_funcs,
> +				       formats, ARRAY_SIZE(formats),
> +				       DRM_PLANE_TYPE_PRIMARY, NULL);
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	drm_plane_helper_add(plane, &intelvipfb_plane_helper_funcs);
> +
> +	return plane;
> +}
> +
> +int intelvipfb_setup_crtc(struct drm_device *drm)
> +{
> +	struct drm_crtc *crtc;
> +	struct drm_plane *primary;
> +	int ret;
> +
> +	crtc = kzalloc(sizeof(*crtc), GFP_KERNEL);
> +	if (!crtc)
> +		return -ENOMEM;
> +
> +	primary = intelvipfb_plane_init(drm);
> +	if (IS_ERR(primary))
> +		return PTR_ERR(primary);
> +
> +	ret = drm_crtc_init_with_planes(drm, crtc, primary, NULL,
> +					&intelvipfb_crtc_funcs, NULL);
> +
> +	if (ret) {
> +		intelvipfb_plane_destroy(primary);
> +		return ret;
> +	}
> +
> +	drm_crtc_helper_add(crtc, &intelvipfb_crtc_helper_funcs);
> +	return 0;
> +}

Looking at your driver overall, you really want to switch over to the
simple display pipe helpers. See https://dri.freedesktop.org/docs/drm/gpu/drm-kms-helpers.html#simple-kms-helper-reference

There's a few nice examples using this merged now, and a few more floating
around on the m-l. That will simplify your driver a lot.

> diff --git a/drivers/gpu/drm/ivip/intel_vip_drv.h b/drivers/gpu/drm/ivip/intel_vip_drv.h
> new file mode 100644
> index 0000000..657f23c
> --- /dev/null
> +++ b/drivers/gpu/drm/ivip/intel_vip_drv.h
> @@ -0,0 +1,55 @@
> +/*
> + * Copyright (C) 2017 Intel Corporation.
> + *
> + * Intel Video and Image Processing(VIP) Frame Buffer II driver.
> + *
> + * 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.
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authors:
> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
> + *
> + */
> +#ifndef _INTEL_VIP_DRV_H
> +#define _INTEL_VIP_DRV_H
> +#include <linux/io.h>
> +#include <linux/fb.h>
> +
> +#define DRIVER_NAME	"intelvipfb"
> +#define BYTES_PER_PIXEL	4
> +#define PREF_BPP		32
> +#define CRTC_NUM		1
> +#define CONN_NUM		1
> +
> +/* control registers */
> +#define INTELVIPFB_CONTROL		0
> +#define INTELVIPFB_STATUS		0x4
> +#define INTELVIPFB_INTERRUPT		0x8
> +#define INTELVIPFB_FRAME_COUNTER	0xC
> +#define INTELVIPFB_FRAME_DROP		0x10
> +#define INTELVIPFB_FRAME_INFO		0x14
> +#define INTELVIPFB_FRAME_START		0x18
> +#define INTELVIPFB_FRAME_READER		0x1C
> +
> +int intelvipfb_probe(struct device *dev, void __iomem *base);
> +int intelvipfb_remove(struct device *dev);
> +int intelvipfb_setup_crtc(struct drm_device *drm);
> +int intelvipfb_drm_conn_init(struct drm_device *drm);
> +
> +struct intelvipfb_priv {
> +	struct drm_fbdev_cma *fbcma;
> +	struct drm_device *drm;
> +	struct fb_info info;
> +	void	__iomem		*base;
> +};
> +
> +#endif
> diff --git a/drivers/gpu/drm/ivip/intel_vip_of.c b/drivers/gpu/drm/ivip/intel_vip_of.c
> new file mode 100644
> index 0000000..17dff36
> --- /dev/null
> +++ b/drivers/gpu/drm/ivip/intel_vip_of.c
> @@ -0,0 +1,146 @@
> +/*
> + * intel_vip_of.c -- Intel Video and Image Processing(VIP)
> + * Frame Buffer II driver
> + *
> + * This driver supports the Intel VIP Frame Reader component.
> + * More info on the hardware can be found in the Intel Video
> + * and Image Processing Suite User Guide at this address
> + * http://www.altera.com/literature/ug/ug_vip.pdf.
> + *
> + * 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.
> + *
> + * 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.
> + *
> + * Authors:
> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
> + *
> + */
> +
> +#include <linux/fb.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +
> +#include <drm/drm_fb_helper.h>
> +#include "intel_vip_drv.h"
> +
> +/*
> + * Setting up information derived from OF Device Tree Nodes
> + * max-width, max-height, bits per pixel, memory port width
> + */
> +
> +static int intelvipfb_of_setup(struct intelvipfb_priv *fbdata,
> +			       struct platform_device *pdev)
> +{
> +	int ret;
> +	int mem_word_width;
> +	u32 bits_per_color;
> +	struct device_node *np = pdev->dev.of_node;
> +
> +	ret = of_property_read_u32(np, "altr,max-width",
> +				   &fbdata->info.var.xres);
> +	if (ret) {
> +		dev_err(&pdev->dev,
> +			"Missing required parameter 'altr,max-width'");
> +		return ret;
> +	}
> +	fbdata->info.var.xres_virtual = fbdata->info.var.xres;
> +
> +	ret = of_property_read_u32(np, "altr,max-height",
> +				   &fbdata->info.var.yres);
> +	if (ret) {
> +		dev_err(&pdev->dev,
> +			"Missing required parameter 'altr,max-height'");
> +		return ret;
> +	}
> +	fbdata->info.var.yres_virtual = fbdata->info.var.yres;
> +
> +	ret = of_property_read_u32(np, "altr,bits-per-symbol", &bits_per_color);
> +	if (ret) {
> +		dev_err(&pdev->dev,
> +			"Missing required parameter 'altr,bits-per-symbol'");
> +		return ret;
> +	}
> +
> +	fbdata->info.var.bits_per_pixel = bits_per_color * BYTES_PER_PIXEL;
> +
> +	ret = of_property_read_u32(np, "altr,mem-port-width", &mem_word_width);
> +	if (ret) {
> +		dev_err(&pdev->dev,
> +			"Missing required parameter 'altr,mem-port-width '");
> +		return ret;
> +	}
> +
> +	if (!(mem_word_width >= 32 && mem_word_width % 32 == 0)) {
> +		dev_err(&pdev->dev,
> +			"mem-word-width is set to %i. must be >= 32 and multiple of 32.",
> +			 mem_word_width);
> +		return -ENODEV;
> +	}
> +
> +	return 0;
> +}

I think we want this as a generic helper in drm_of.c, and instead of going
through the fbdev/legacy struct fb_info, directly fill out
drm_device->mode_config.

This assumes ofc that this is a generic DT thing. If not, then please
remove the fb_info indirection, I guess this is porting leftovers from
this being an fb driver?

> +
> +static int intelvipfb_of_probe(struct platform_device *pdev)
> +{
> +	int retval;
> +	struct resource *reg_res;
> +	struct intelvipfb_priv *fbdata;
> +
> +	fbdata = devm_kzalloc(&pdev->dev, sizeof(*fbdata), GFP_KERNEL);
> +	if (!fbdata)
> +		return -ENOMEM;
> +
> +	reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!reg_res)
> +		return -ENOMEM;
> +
> +	fbdata->base = devm_ioremap_resource(&pdev->dev, reg_res);
> +
> +	if (IS_ERR(fbdata->base)) {
> +		dev_err(&pdev->dev, "devm_ioremap_resource failed\n");
> +		retval = PTR_ERR(fbdata->base);
> +		return -ENOMEM;
> +	}
> +
> +	intelvipfb_of_setup(fbdata, pdev);
> +
> +	platform_set_drvdata(pdev, fbdata);
> +
> +	return intelvipfb_probe(&pdev->dev, fbdata->base);
> +}
> +
> +static int intelvipfb_of_remove(struct platform_device *pdev)
> +{
> +	return intelvipfb_remove(&pdev->dev);
> +}
> +
> +/*
> + * The name vip-frame-buffer-2.0 is derived from
> + * http://www.altera.com/literature/ug/ug_vip.pdf
> + * frame buffer IP cores section 14
> + */
> +
> +static const struct of_device_id intelvipfb_of_match[] = {
> +	{ .compatible = "altr,vip-frame-buffer-2.0" },
> +	{},
> +};
> +
> +MODULE_DEVICE_TABLE(of, intelvipfb_of_match);
> +
> +static struct platform_driver intelvipfb_driver = {
> +	.probe = intelvipfb_of_probe,
> +	.remove = intelvipfb_of_remove,
> +	.driver = {
> +		.name = DRIVER_NAME,
> +		.of_match_table = intelvipfb_of_match,
> +	},
> +};
> +
> +module_platform_driver(intelvipfb_driver);
> -- 
> 1.7.1
> 

> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel


-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: DRM Display driver for Intel FPGA Video and Image Processing Suite
  2017-03-31  9:08 DRM Display driver for Intel FPGA Video and Image Processing Suite Ong, Hean Loong
  2017-04-02 12:42 ` Daniel Vetter
@ 2017-04-04  4:01 ` Ong, Hean Loong
  2017-04-06  6:29   ` Ong, Hean Loong
  1 sibling, 1 reply; 9+ messages in thread
From: Ong, Hean Loong @ 2017-04-04  4:01 UTC (permalink / raw)
  To: Vetter, Daniel, airlied; +Cc: dri-devel

Hi All,

Apologies for the attachment earlier. Below are the inline changes for the patch

From 0de293e3646a1780ed603cf8e1f2a19d9aebbe83 Mon Sep 17 00:00:00 2001
From: Ong, Hean Loong <hean.loong.ong@intel.com>
Date: Thu, 30 Mar 2017 18:02:22 +0800
Subject: [PATCHv0] Intel FPGA Video and Image Processing Suite Frame Buffer II driver

Signed-off-by: Ong, Hean Loong <hean.loong.ong@intel.com>
---
 drivers/gpu/drm/Kconfig               |    2 +
 drivers/gpu/drm/Makefile              |    1 +
 drivers/gpu/drm/ivip/Kconfig          |   22 ++++
 drivers/gpu/drm/ivip/Makefile         |    9 ++
 drivers/gpu/drm/ivip/intel_vip_conn.c |  145 ++++++++++++++++++++++
 drivers/gpu/drm/ivip/intel_vip_core.c |  215 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/ivip/intel_vip_crtc.c |  161 ++++++++++++++++++++++++
 drivers/gpu/drm/ivip/intel_vip_drv.h  |   55 +++++++++
 drivers/gpu/drm/ivip/intel_vip_of.c   |  146 ++++++++++++++++++++++
 9 files changed, 756 insertions(+), 0 deletions(-)
 create mode 100644 drivers/gpu/drm/ivip/Kconfig
 create mode 100644 drivers/gpu/drm/ivip/Makefile
 create mode 100644 drivers/gpu/drm/ivip/intel_vip_conn.c
 create mode 100644 drivers/gpu/drm/ivip/intel_vip_core.c
 create mode 100644 drivers/gpu/drm/ivip/intel_vip_crtc.c
 create mode 100644 drivers/gpu/drm/ivip/intel_vip_drv.h
 create mode 100644 drivers/gpu/drm/ivip/intel_vip_of.c

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index ebfe840..c487507 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -167,6 +167,8 @@ source "drivers/gpu/drm/nouveau/Kconfig"
 
 source "drivers/gpu/drm/i915/Kconfig"
 
+source "drivers/gpu/drm/ivip/Kconfig"
+
 config DRM_VGEM
 	tristate "Virtual GEM provider"
 	depends on DRM
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index b9ae428..945cf53 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/
 obj-$(CONFIG_DRM_MGA)	+= mga/
 obj-$(CONFIG_DRM_I810)	+= i810/
 obj-$(CONFIG_DRM_I915)	+= i915/
+obj-$(CONFIG_DRM_IVIP)	+= ivip/
 obj-$(CONFIG_DRM_MGAG200) += mgag200/
 obj-$(CONFIG_DRM_VC4)  += vc4/
 obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus/
diff --git a/drivers/gpu/drm/ivip/Kconfig b/drivers/gpu/drm/ivip/Kconfig
new file mode 100644
index 0000000..ddf3cb5
--- /dev/null
+++ b/drivers/gpu/drm/ivip/Kconfig
@@ -0,0 +1,22 @@
+config DRM_IVIP
+        tristate "Intel FGPA Video and Image Processing"
+        depends on DRM
+        select DRM_GEM_CMA_HELPER
+        select DRM_KMS_HELPER
+        select DRM_KMS_FB_HELPER
+        select DRM_KMS_CMA_HELPER
+        help
+                Choose this option if you have a Intel FPGA Arria 10 system
+                and above with a Display Port IP. This does not support legacy
+                Intel FPGA Cyclone V display port. Currently only single frame
+                buffer is supported. Note that ACPI and X_86 architecture is yet
+                to be supported.
+
+config DRM_IVIP_OF
+        tristate "Intel FGPA Video and Image Processing Open Firmware Systems"
+        depends on DRM_IVIP && OF
+        help
+                Choose this option if the Intel FPGA system is using Open
+                Firmware systems (Arria 10). If M is selected the module would
+                be called ivip.
+
diff --git a/drivers/gpu/drm/ivip/Makefile b/drivers/gpu/drm/ivip/Makefile
new file mode 100644
index 0000000..7be1e99
--- /dev/null
+++ b/drivers/gpu/drm/ivip/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the drm device driver.  This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+
+ccflags-y := -Iinclude/drm
+
+obj-$(CONFIG_DRM_IVIP_OF) += ivip.o
+ivip-objs := intel_vip_of.o intel_vip_core.o \
+intel_vip_conn.o intel_vip_crtc.o
diff --git a/drivers/gpu/drm/ivip/intel_vip_conn.c b/drivers/gpu/drm/ivip/intel_vip_conn.c
new file mode 100644
index 0000000..89ab587
--- /dev/null
+++ b/drivers/gpu/drm/ivip/intel_vip_conn.c
@@ -0,0 +1,145 @@
+/*
+ * intel_vip_conn.c -- Intel Video and Image Processing(VIP)
+ * Frame Buffer II driver
+ *
+ * This driver supports the Intel VIP Frame Reader component.
+ * More info on the hardware can be found in the Intel Video
+ * and Image Processing Suite User Guide at this address
+ * http://www.altera.com/literature/ug/ug_vip.pdf.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * Authors:
+ * Ong, Hean-Loong <hean.loong.ong@intel.com>
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder_slave.h>
+#include <drm/drm_plane_helper.h>
+
+static enum drm_connector_status
+intelvipfb_drm_connector_detect(struct drm_connector *connector, bool force)
+{
+	return connector_status_connected;
+}
+
+static void intelvipfb_drm_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_funcs intelvipfb_drm_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.reset = drm_atomic_helper_connector_reset,
+	.detect = intelvipfb_drm_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = intelvipfb_drm_connector_destroy,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int intelvipfb_drm_connector_get_modes(struct drm_connector *connector)
+{
+	struct drm_device *drm = connector->dev;
+	int count;
+
+	count = drm_add_modes_noedid(connector, drm->mode_config.max_width,
+				     drm->mode_config.max_height);
+	drm_set_preferred_mode(connector, drm->mode_config.max_width,
+			       drm->mode_config.max_height);
+	return count;
+}
+
+static const struct drm_connector_helper_funcs
+intelvipfb_drm_connector_helper_funcs = {
+	.get_modes = intelvipfb_drm_connector_get_modes,
+};
+
+static const struct drm_encoder_funcs
+intelvipfb_drm_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+static void intelvipfb_mode_set(struct drm_encoder *encoder,
+				struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode)
+{
+	/* do nothing */
+}
+
+static void intelvipfb_nop(struct drm_encoder *encoder)
+{
+	/* do nothing */
+}
+
+static const struct drm_encoder_helper_funcs i
+intelvipfb_drm_encoder_helper = {
+	.mode_set = intelvipfb_mode_set,
+	.enable = intelvipfb_nop,
+	.disable = intelvipfb_nop,
+};
+
+int intelvipfb_drm_conn_init(struct drm_device *drm)
+{
+	struct drm_encoder_slave *encoder;
+	struct drm_connector *conn;
+	int ret;
+
+	encoder = devm_kzalloc(drm->dev, sizeof(*encoder), GFP_KERNEL);
+	if (!encoder)
+		return -ENOMEM;
+
+	encoder->base.possible_crtcs = 1;
+	encoder->base.possible_clones = 0;
+
+	ret = drm_encoder_init(drm, &encoder->base,
+			       &intelvipfb_drm_encoder_funcs,
+			       DRM_MODE_ENCODER_VIRTUAL, NULL);
+	if (ret)
+		return ret;
+
+	drm_encoder_helper_add(&encoder->base, &intelvipfb_drm_encoder_helper);
+
+	conn = devm_kzalloc(drm->dev, sizeof(*conn), GFP_KERNEL);
+	if (IS_ERR(conn))
+		return PTR_ERR(conn);
+
+	ret = drm_connector_init(drm, conn, &intelvipfb_drm_connector_funcs,
+				 DRM_MODE_CONNECTOR_DisplayPort);
+	if (ret < 0) {
+		dev_err(drm->dev, "failed to initialize drm connector\n");
+		ret = -ENOMEM;
+		goto error_encoder_cleanup;
+	}
+
+	drm_connector_helper_add(conn, &intelvipfb_drm_connector_helper_funcs);
+
+	ret = drm_mode_connector_attach_encoder(conn, &encoder->base);
+	if (ret < 0) {
+		dev_err(drm->dev, "could not attach connector to encoder\n");
+		drm_connector_unregister(conn);
+		goto error_connector_cleanup;
+	}
+
+	return 0;
+
+error_connector_cleanup:
+	drm_connector_cleanup(conn);
+
+error_encoder_cleanup:
+	drm_encoder_cleanup(&encoder->base);
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/ivip/intel_vip_core.c b/drivers/gpu/drm/ivip/intel_vip_core.c
new file mode 100644
index 0000000..3001ad0
--- /dev/null
+++ b/drivers/gpu/drm/ivip/intel_vip_core.c
@@ -0,0 +1,215 @@
+/*
+ * intel_vip_core.c -- Intel Video and Image Processing(VIP)
+ * Frame Buffer II driver
+ *
+ * This driver supports the Intel VIP Frame Reader component.
+ * More info on the hardware can be found in the Intel Video
+ * and Image Processing Suite User Guide at this address
+ * http://www.altera.com/literature/ug/ug_vip.pdf.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * Authors:
+ * Ong, Hean-Loong <hean.loong.ong@intel.com>
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_of.h>
+
+#include "intel_vip_drv.h"
+
+static const struct file_operations intelvipfb_drm_fops = {
+	.owner		= THIS_MODULE,
+	.open		= drm_open,
+	.release	= drm_release,
+	.unlocked_ioctl	= drm_ioctl,
+	.poll		= drm_poll,
+	.read		= drm_read,
+	.llseek		= no_llseek,
+	.mmap		= drm_gem_cma_mmap,
+};
+
+static void intelvipfb_lastclose(struct drm_device *drm)
+{
+	struct intelvipfb_priv *fbpriv = drm->dev_private;
+
+	drm_fbdev_cma_restore_mode(fbpriv->fbcma);
+}
+
+static struct drm_driver intelvipfb_drm = {
+	.driver_features =
+	    DRIVER_GEM | DRIVER_PRIME |
+	    DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC,
+	.gem_free_object_unlocked = drm_gem_cma_free_object,
+	.gem_vm_ops = &drm_gem_cma_vm_ops,
+	.dumb_create = drm_gem_cma_dumb_create,
+	.dumb_map_offset = drm_gem_cma_dumb_map_offset,
+	.dumb_destroy = drm_gem_dumb_destroy,
+	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+	.gem_prime_export = drm_gem_prime_export,
+	.gem_prime_import = drm_gem_prime_import,
+	.gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
+	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+	.gem_prime_vmap = drm_gem_cma_prime_vmap,
+	.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
+	.gem_prime_mmap = drm_gem_cma_prime_mmap,
+	.name = DRIVER_NAME,
+	.date = "20170329",
+	.desc = "Intel FPGA VIP SUITE",
+	.major = 1,
+	.minor = 0,
+	.patchlevel = 0,
+	.lastclose = intelvipfb_lastclose,
+	.fops = &intelvipfb_drm_fops,
+};
+
+static void intelvipfb_start_hw(void __iomem *base, resource_size_t addr)
+{
+	/*
+	 * The frameinfo variable has to correspond to the size of the VIP Suite
+	 * Frame Reader register 7 which will determine the maximum size used
+	 * in this frameinfo
+	 */
+
+	u32 frameinfo;
+
+	frameinfo =
+		readl(base + INTELVIPFB_FRAME_READER) & 0x00ffffff;
+
+	writel(frameinfo, base + INTELVIPFB_FRAME_INFO);
+
+	writel(addr, base + INTELVIPFB_FRAME_START);
+	/* Finally set the control register to 1 to start streaming */
+	writel(1, base + INTELVIPFB_CONTROL);
+}
+
+static void intelvipfb_disable_hw(void __iomem *base)
+{
+	/* set the control register to 0 to stop streaming */
+	writel(0, base + INTELVIPFB_CONTROL);
+}
+
+static void intelvipfb_output_poll_changed(struct drm_device *drm)
+{
+	struct intelvipfb_priv *fbpriv = drm->dev_private;
+
+	drm_fbdev_cma_hotplug_event(fbpriv->fbcma);
+}
+
+static const struct drm_mode_config_funcs intelvipfb_mode_config_funcs = {
+	.fb_create = drm_fb_cma_create,
+	.output_poll_changed = intelvipfb_output_poll_changed,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = drm_atomic_helper_commit,
+};
+
+static struct drm_mode_config_helper_funcs intelvipfb_mode_config_helpers = {
+	.atomic_commit_tail = drm_atomic_helper_commit_tail,
+};
+
+static void intelvipfb_setup_mode_config(struct drm_device *drm,
+					 struct fb_info *info)
+{
+	drm_mode_config_init(drm);
+	drm->mode_config.min_width = 0;
+	drm->mode_config.min_height = 0;
+	drm->mode_config.max_width = info->var.xres;
+	drm->mode_config.max_height = info->var.yres;
+	drm->mode_config.preferred_depth = 32;
+	drm->mode_config.funcs = &intelvipfb_mode_config_funcs;
+	drm->mode_config.helper_private = &intelvipfb_mode_config_helpers;
+}
+
+int intelvipfb_probe(struct device *dev, void __iomem *base)
+{
+	int retval;
+	struct drm_device *drm;
+	struct intelvipfb_priv *fbpriv = dev_get_drvdata(dev);
+	struct fb_info *info = &fbpriv->info;
+
+	/*setup DRM */
+	drm = drm_dev_alloc(&intelvipfb_drm, dev);
+	if (IS_ERR(drm))
+		return PTR_ERR(drm);
+
+	drm->dev_private = fbpriv;
+
+	dev_set_drvdata(dev, drm);
+
+	intelvipfb_setup_mode_config(drm, info);
+
+	retval = dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32));
+	if (retval)
+		return -ENODEV;
+
+	retval = intelvipfb_setup_crtc(drm);
+	if (retval < 0)
+		return -ENODEV;
+
+	retval = intelvipfb_drm_conn_init(drm);
+	if (retval)
+		return -ENOMEM;
+
+	drm_mode_config_reset(drm);
+
+	fbpriv->fbcma = drm_fbdev_cma_init(drm, PREF_BPP,
+							CRTC_NUM, CONN_NUM);
+	if (!fbpriv->fbcma) {
+		fbpriv->fbcma = NULL;
+		return -ENODEV;
+	}
+
+	intelvipfb_start_hw(base, drm->mode_config.fb_base);
+
+	drm_kms_helper_poll_init(drm);
+
+	drm_dev_register(drm, 0);
+
+	return retval;
+}
+EXPORT_SYMBOL_GPL(intelvipfb_probe);
+
+int intelvipfb_remove(struct device *dev)
+{
+	struct drm_device *drm = dev_get_drvdata(dev);
+	struct intelvipfb_priv *fbpriv = drm->dev_private;
+
+	drm_dev_unregister(drm);
+
+	drm_kms_helper_poll_fini(drm);
+	drm_fbdev_cma_fini(fbpriv->fbcma);
+
+	intelvipfb_disable_hw(fbpriv->base);
+
+drm_mode_config_cleanup(drm);
+
+drm_dev_unref(drm);
+
+devm_kfree(dev, fbpriv);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(intelvipfb_remove);
+
+MODULE_AUTHOR("Ong, Hean-Loong <hean.loong.ong@intel.com>");
+MODULE_DESCRIPTION("Intel VIP Frame Buffer II driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/ivip/intel_vip_crtc.c b/drivers/gpu/drm/ivip/intel_vip_crtc.c
new file mode 100644
index 0000000..97a3954
--- /dev/null
+++ b/drivers/gpu/drm/ivip/intel_vip_crtc.c
@@ -0,0 +1,161 @@
+/*
+ * intel_vip_crtc.c -- Intel Video and Image Processing(VIP)
+ * Frame Buffer II driver
+ *
+ * This driver supports the Intel VIP Frame Reader component.
+ * More info on the hardware can be found in the Intel Video
+ * and Image Processing Suite User Guide at this address
+ * http://www.altera.com/literature/ug/ug_vip.pdf.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * Authors:
+ * Ong, Hean-Loong <hean.loong.ong@intel.com>
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_data/simplefb.h>
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_plane_helper.h>
+
+#include "intel_vip_drv.h"
+
+static struct simplefb_format intelvipfb_formats[] = SIMPLEFB_FORMATS;
+
+static void intelvipfb_crtc_destroy(struct drm_crtc *crtc)
+{
+	drm_crtc_cleanup(crtc);
+	kfree(crtc);
+}
+
+static const struct drm_crtc_funcs intelvipfb_crtc_funcs = {
+	.destroy = intelvipfb_crtc_destroy,
+	.set_config = drm_atomic_helper_set_config,
+	.page_flip = drm_atomic_helper_page_flip,
+	.reset = drm_atomic_helper_crtc_reset,
+	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+};
+
+static void intelvipfb_crtc_atomic_begin(struct drm_crtc *crtc,
+					 struct drm_crtc_state *state)
+{
+	struct drm_pending_vblank_event *event = crtc->state->event;
+
+	if (event) {
+		crtc->state->event = NULL;
+
+		spin_lock_irq(&crtc->dev->event_lock);
+		drm_crtc_send_vblank_event(crtc, event);
+		spin_unlock_irq(&crtc->dev->event_lock);
+	}
+}
+
+static void intelvipfb_crtc_nop(struct drm_crtc *crtc)
+{
+	/* do nothing */;
+}
+
+static const struct drm_crtc_helper_funcs intelvipfb_crtc_helper_funcs = {
+	.atomic_begin	= intelvipfb_crtc_atomic_begin,
+	.enable = intelvipfb_crtc_nop,
+};
+
+static void intelvipfb_plane_destroy(struct drm_plane *plane)
+{
+	drm_plane_helper_disable(plane);
+	drm_plane_cleanup(plane);
+}
+
+static const struct drm_plane_funcs intelvipfb_plane_funcs = {
+	.update_plane		= drm_atomic_helper_update_plane,
+	.disable_plane		= drm_atomic_helper_disable_plane,
+	.destroy		= intelvipfb_plane_destroy,
+	.reset			= drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
+};
+
+static void intelvipfb_plane_atomic_update(struct drm_plane *plane,
+					   struct drm_plane_state *state)
+{
+	struct intelvipfb_priv *fbpriv;
+	struct drm_gem_cma_object *gem;
+
+	if (!plane->state->crtc || !plane->state->fb)
+		return;
+
+	fbpriv = plane->dev->dev_private;
+	gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
+	writel(gem->paddr, fbpriv->base + INTELVIPFB_FRAME_START);
+}
+
+static const struct drm_plane_helper_funcs intelvipfb_plane_helper_funcs = {
+	.atomic_update = intelvipfb_plane_atomic_update,
+};
+
+static struct drm_plane *intelvipfb_plane_init(struct drm_device *drm)
+{
+	struct drm_plane *plane = NULL;
+	u32 formats[ARRAY_SIZE(intelvipfb_formats)], i;
+	int ret;
+
+	plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
+	if (!plane)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < ARRAY_SIZE(intelvipfb_formats); i++)
+		formats[i] = intelvipfb_formats[i].fourcc;
+
+	ret = drm_universal_plane_init(drm, plane, 0xff,
+				       &intelvipfb_plane_funcs,
+				       formats, ARRAY_SIZE(formats),
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret)
+		return ERR_PTR(ret);
+
+	drm_plane_helper_add(plane, &intelvipfb_plane_helper_funcs);
+
+	return plane;
+}
+
+int intelvipfb_setup_crtc(struct drm_device *drm)
+{
+	struct drm_crtc *crtc;
+	struct drm_plane *primary;
+	int ret;
+
+	crtc = kzalloc(sizeof(*crtc), GFP_KERNEL);
+	if (!crtc)
+		return -ENOMEM;
+
+	primary = intelvipfb_plane_init(drm);
+	if (IS_ERR(primary))
+		return PTR_ERR(primary);
+
+	ret = drm_crtc_init_with_planes(drm, crtc, primary, NULL,
+					&intelvipfb_crtc_funcs, NULL);
+
+	if (ret) {
+		intelvipfb_plane_destroy(primary);
+		return ret;
+	}
+
+	drm_crtc_helper_add(crtc, &intelvipfb_crtc_helper_funcs);
+	return 0;
+}
diff --git a/drivers/gpu/drm/ivip/intel_vip_drv.h b/drivers/gpu/drm/ivip/intel_vip_drv.h
new file mode 100644
index 0000000..657f23c
--- /dev/null
+++ b/drivers/gpu/drm/ivip/intel_vip_drv.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2017 Intel Corporation.
+ *
+ * Intel Video and Image Processing(VIP) Frame Buffer II driver.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Ong, Hean-Loong <hean.loong.ong@intel.com>
+ *
+ */
+#ifndef _INTEL_VIP_DRV_H
+#define _INTEL_VIP_DRV_H
+#include <linux/io.h>
+#include <linux/fb.h>
+
+#define DRIVER_NAME	"intelvipfb"
+#define BYTES_PER_PIXEL	4
+#define PREF_BPP		32
+#define CRTC_NUM		1
+#define CONN_NUM		1
+
+/* control registers */
+#define INTELVIPFB_CONTROL		0
+#define INTELVIPFB_STATUS		0x4
+#define INTELVIPFB_INTERRUPT		0x8
+#define INTELVIPFB_FRAME_COUNTER	0xC
+#define INTELVIPFB_FRAME_DROP		0x10
+#define INTELVIPFB_FRAME_INFO		0x14
+#define INTELVIPFB_FRAME_START		0x18
+#define INTELVIPFB_FRAME_READER		0x1C
+
+int intelvipfb_probe(struct device *dev, void __iomem *base);
+int intelvipfb_remove(struct device *dev);
+int intelvipfb_setup_crtc(struct drm_device *drm);
+int intelvipfb_drm_conn_init(struct drm_device *drm);
+
+struct intelvipfb_priv {
+	struct drm_fbdev_cma *fbcma;
+	struct drm_device *drm;
+	struct fb_info info;
+	void	__iomem		*base;
+};
+
+#endif
diff --git a/drivers/gpu/drm/ivip/intel_vip_of.c b/drivers/gpu/drm/ivip/intel_vip_of.c
new file mode 100644
index 0000000..17dff36
--- /dev/null
+++ b/drivers/gpu/drm/ivip/intel_vip_of.c
@@ -0,0 +1,146 @@
+/*
+ * intel_vip_of.c -- Intel Video and Image Processing(VIP)
+ * Frame Buffer II driver
+ *
+ * This driver supports the Intel VIP Frame Reader component.
+ * More info on the hardware can be found in the Intel Video
+ * and Image Processing Suite User Guide at this address
+ * http://www.altera.com/literature/ug/ug_vip.pdf.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * Authors:
+ * Ong, Hean-Loong <hean.loong.ong@intel.com>
+ *
+ */
+
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <drm/drm_fb_helper.h>
+#include "intel_vip_drv.h"
+
+/*
+ * Setting up information derived from OF Device Tree Nodes
+ * max-width, max-height, bits per pixel, memory port width
+ */
+
+static int intelvipfb_of_setup(struct intelvipfb_priv *fbdata,
+			       struct platform_device *pdev)
+{
+	int ret;
+	int mem_word_width;
+	u32 bits_per_color;
+	struct device_node *np = pdev->dev.of_node;
+
+	ret = of_property_read_u32(np, "altr,max-width",
+				   &fbdata->info.var.xres);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Missing required parameter 'altr,max-width'");
+		return ret;
+	}
+	fbdata->info.var.xres_virtual = fbdata->info.var.xres;
+
+	ret = of_property_read_u32(np, "altr,max-height",
+				   &fbdata->info.var.yres);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Missing required parameter 'altr,max-height'");
+		return ret;
+	}
+	fbdata->info.var.yres_virtual = fbdata->info.var.yres;
+
+	ret = of_property_read_u32(np, "altr,bits-per-symbol", &bits_per_color);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Missing required parameter 'altr,bits-per-symbol'");
+		return ret;
+	}
+
+	fbdata->info.var.bits_per_pixel = bits_per_color * BYTES_PER_PIXEL;
+
+	ret = of_property_read_u32(np, "altr,mem-port-width", &mem_word_width);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Missing required parameter 'altr,mem-port-width '");
+		return ret;
+	}
+
+	if (!(mem_word_width >= 32 && mem_word_width % 32 == 0)) {
+		dev_err(&pdev->dev,
+			"mem-word-width is set to %i. must be >= 32 and multiple of 32.",
+			 mem_word_width);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int intelvipfb_of_probe(struct platform_device *pdev)
+{
+	int retval;
+	struct resource *reg_res;
+	struct intelvipfb_priv *fbdata;
+
+	fbdata = devm_kzalloc(&pdev->dev, sizeof(*fbdata), GFP_KERNEL);
+	if (!fbdata)
+		return -ENOMEM;
+
+	reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!reg_res)
+		return -ENOMEM;
+
+	fbdata->base = devm_ioremap_resource(&pdev->dev, reg_res);
+
+	if (IS_ERR(fbdata->base)) {
+		dev_err(&pdev->dev, "devm_ioremap_resource failed\n");
+		retval = PTR_ERR(fbdata->base);
+		return -ENOMEM;
+	}
+
+	intelvipfb_of_setup(fbdata, pdev);
+
+	platform_set_drvdata(pdev, fbdata);
+
+	return intelvipfb_probe(&pdev->dev, fbdata->base);
+}
+
+static int intelvipfb_of_remove(struct platform_device *pdev)
+{
+	return intelvipfb_remove(&pdev->dev);
+}
+
+/*
+ * The name vip-frame-buffer-2.0 is derived from
+ * http://www.altera.com/literature/ug/ug_vip.pdf
+ * frame buffer IP cores section 14
+ */
+
+static const struct of_device_id intelvipfb_of_match[] = {
+	{ .compatible = "altr,vip-frame-buffer-2.0" },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, intelvipfb_of_match);
+
+static struct platform_driver intelvipfb_driver = {
+	.probe = intelvipfb_of_probe,
+	.remove = intelvipfb_of_remove,
+	.driver = {
+		.name = DRIVER_NAME,
+		.of_match_table = intelvipfb_of_match,
+	},
+};
+
+module_platform_driver(intelvipfb_driver);
-- 
1.7.1


-----Original Message-----
From: Ong, Hean Loong 
Sent: Friday, March 31, 2017 5:09 PM
To: Vetter, Daniel <daniel.vetter@intel.com>; airlied@linux.ie
Cc: dri-devel@lists.freedesktop.org
Subject: DRM Display driver for Intel FPGA Video and Image Processing Suite

Hi,

I would like to upstream the attached Intel FPGA Video and Image Processing Suite. The attached patch supports the Intel Arria10 devkit and its variants. The purpose of the patch is to enable the FPGA driven display designed from the Intel Quartus FPGA design suite.

The driver is required as part of the Intel Arria10 devkit reference design. The driver was tested on:
- The Open Embedded Angstrom Distro.
- The matchbox-terminal and window-manager was used for functional testing

Current the intention of the driver is meant to validate the FPGA designs on the Arria10 devkit for Display Port connecter. We have not verified its performance of or stability in 3D acceleration or other non Intel FPGA hardware

BR

Hean Loong
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: DRM Display driver for Intel FPGA Video and Image Processing Suite
  2017-04-04  4:01 ` Ong, Hean Loong
@ 2017-04-06  6:29   ` Ong, Hean Loong
  2017-04-07 16:31     ` Daniel Vetter
  0 siblings, 1 reply; 9+ messages in thread
From: Ong, Hean Loong @ 2017-04-06  6:29 UTC (permalink / raw)
  To: Vetter, Daniel, airlied; +Cc: dri-devel

Hi All,

Any comments for the patch below?

Thanks

Hean Loong

On Tue, 2017-04-04 at 04:01 +0000, Ong, Hean Loong wrote:
> Hi All,
> 
> Apologies for the attachment earlier. Below are the inline changes
> for the patch
> 
> From 0de293e3646a1780ed603cf8e1f2a19d9aebbe83 Mon Sep 17 00:00:00
> 2001
> From: Ong, Hean Loong <hean.loong.ong@intel.com>
> Date: Thu, 30 Mar 2017 18:02:22 +0800
> Subject: [PATCHv0] Intel FPGA Video and Image Processing Suite Frame
> Buffer II driver
> 
> Signed-off-by: Ong, Hean Loong <hean.loong.ong@intel.com>
> ---
>  drivers/gpu/drm/Kconfig               |    2 +
>  drivers/gpu/drm/Makefile              |    1 +
>  drivers/gpu/drm/ivip/Kconfig          |   22 ++++
>  drivers/gpu/drm/ivip/Makefile         |    9 ++
>  drivers/gpu/drm/ivip/intel_vip_conn.c |  145 ++++++++++++++++++++++
>  drivers/gpu/drm/ivip/intel_vip_core.c |  215
> +++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/ivip/intel_vip_crtc.c |  161
> ++++++++++++++++++++++++
>  drivers/gpu/drm/ivip/intel_vip_drv.h  |   55 +++++++++
>  drivers/gpu/drm/ivip/intel_vip_of.c   |  146 ++++++++++++++++++++++
>  9 files changed, 756 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/gpu/drm/ivip/Kconfig
>  create mode 100644 drivers/gpu/drm/ivip/Makefile
>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_conn.c
>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_core.c
>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_crtc.c
>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_drv.h
>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_of.c
> 
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index ebfe840..c487507 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
> @@ -167,6 +167,8 @@ source "drivers/gpu/drm/nouveau/Kconfig"
>  
>  source "drivers/gpu/drm/i915/Kconfig"
>  
> +source "drivers/gpu/drm/ivip/Kconfig"
> +
>  config DRM_VGEM
>  	tristate "Virtual GEM provider"
>  	depends on DRM
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index b9ae428..945cf53 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -52,6 +52,7 @@ obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/
>  obj-$(CONFIG_DRM_MGA)	+= mga/
>  obj-$(CONFIG_DRM_I810)	+= i810/
>  obj-$(CONFIG_DRM_I915)	+= i915/
> +obj-$(CONFIG_DRM_IVIP)	+= ivip/
>  obj-$(CONFIG_DRM_MGAG200) += mgag200/
>  obj-$(CONFIG_DRM_VC4)  += vc4/
>  obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus/
> diff --git a/drivers/gpu/drm/ivip/Kconfig
> b/drivers/gpu/drm/ivip/Kconfig
> new file mode 100644
> index 0000000..ddf3cb5
> --- /dev/null
> +++ b/drivers/gpu/drm/ivip/Kconfig
> @@ -0,0 +1,22 @@
> +config DRM_IVIP
> +        tristate "Intel FGPA Video and Image Processing"
> +        depends on DRM
> +        select DRM_GEM_CMA_HELPER
> +        select DRM_KMS_HELPER
> +        select DRM_KMS_FB_HELPER
> +        select DRM_KMS_CMA_HELPER
> +        help
> +                Choose this option if you have a Intel FPGA Arria 10
> system
> +                and above with a Display Port IP. This does not
> support legacy
> +                Intel FPGA Cyclone V display port. Currently only
> single frame
> +                buffer is supported. Note that ACPI and X_86
> architecture is yet
> +                to be supported.
> +
> +config DRM_IVIP_OF
> +        tristate "Intel FGPA Video and Image Processing Open
> Firmware Systems"
> +        depends on DRM_IVIP && OF
> +        help
> +                Choose this option if the Intel FPGA system is using
> Open
> +                Firmware systems (Arria 10). If M is selected the
> module would
> +                be called ivip.
> +
> diff --git a/drivers/gpu/drm/ivip/Makefile
> b/drivers/gpu/drm/ivip/Makefile
> new file mode 100644
> index 0000000..7be1e99
> --- /dev/null
> +++ b/drivers/gpu/drm/ivip/Makefile
> @@ -0,0 +1,9 @@
> +#
> +# Makefile for the drm device driver.  This driver provides support
> for the
> +# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
> +
> +ccflags-y := -Iinclude/drm
> +
> +obj-$(CONFIG_DRM_IVIP_OF) += ivip.o
> +ivip-objs := intel_vip_of.o intel_vip_core.o \
> +intel_vip_conn.o intel_vip_crtc.o
> diff --git a/drivers/gpu/drm/ivip/intel_vip_conn.c
> b/drivers/gpu/drm/ivip/intel_vip_conn.c
> new file mode 100644
> index 0000000..89ab587
> --- /dev/null
> +++ b/drivers/gpu/drm/ivip/intel_vip_conn.c
> @@ -0,0 +1,145 @@
> +/*
> + * intel_vip_conn.c -- Intel Video and Image Processing(VIP)
> + * Frame Buffer II driver
> + *
> + * This driver supports the Intel VIP Frame Reader component.
> + * More info on the hardware can be found in the Intel Video
> + * and Image Processing Suite User Guide at this address
> + * http://www.altera.com/literature/ug/ug_vip.pdf.
> + *
> + * 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.
> + *
> + * 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.
> + *
> + * Authors:
> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
> + *
> + */
> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder_slave.h>
> +#include <drm/drm_plane_helper.h>
> +
> +static enum drm_connector_status
> +intelvipfb_drm_connector_detect(struct drm_connector *connector,
> bool force)
> +{
> +	return connector_status_connected;
> +}
> +
> +static void intelvipfb_drm_connector_destroy(struct drm_connector
> *connector)
> +{
> +	drm_connector_unregister(connector);
> +	drm_connector_cleanup(connector);
> +}
> +
> +static const struct drm_connector_funcs
> intelvipfb_drm_connector_funcs = {
> +	.dpms = drm_helper_connector_dpms,
> +	.reset = drm_atomic_helper_connector_reset,
> +	.detect = intelvipfb_drm_connector_detect,
> +	.fill_modes = drm_helper_probe_single_connector_modes,
> +	.destroy = intelvipfb_drm_connector_destroy,
> +	.atomic_duplicate_state =
> drm_atomic_helper_connector_duplicate_state,
> +	.atomic_destroy_state =
> drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static int intelvipfb_drm_connector_get_modes(struct drm_connector
> *connector)
> +{
> +	struct drm_device *drm = connector->dev;
> +	int count;
> +
> +	count = drm_add_modes_noedid(connector, drm-
> >mode_config.max_width,
> +				     drm->mode_config.max_height);
> +	drm_set_preferred_mode(connector, drm-
> >mode_config.max_width,
> +			       drm->mode_config.max_height);
> +	return count;
> +}
> +
> +static const struct drm_connector_helper_funcs
> +intelvipfb_drm_connector_helper_funcs = {
> +	.get_modes = intelvipfb_drm_connector_get_modes,
> +};
> +
> +static const struct drm_encoder_funcs
> +intelvipfb_drm_encoder_funcs = {
> +	.destroy = drm_encoder_cleanup,
> +};
> +
> +static void intelvipfb_mode_set(struct drm_encoder *encoder,
> +				struct drm_display_mode *mode,
> +				struct drm_display_mode
> *adjusted_mode)
> +{
> +	/* do nothing */
> +}
> +
> +static void intelvipfb_nop(struct drm_encoder *encoder)
> +{
> +	/* do nothing */
> +}
> +
> +static const struct drm_encoder_helper_funcs i
> +intelvipfb_drm_encoder_helper = {
> +	.mode_set = intelvipfb_mode_set,
> +	.enable = intelvipfb_nop,
> +	.disable = intelvipfb_nop,
> +};
> +
> +int intelvipfb_drm_conn_init(struct drm_device *drm)
> +{
> +	struct drm_encoder_slave *encoder;
> +	struct drm_connector *conn;
> +	int ret;
> +
> +	encoder = devm_kzalloc(drm->dev, sizeof(*encoder),
> GFP_KERNEL);
> +	if (!encoder)
> +		return -ENOMEM;
> +
> +	encoder->base.possible_crtcs = 1;
> +	encoder->base.possible_clones = 0;
> +
> +	ret = drm_encoder_init(drm, &encoder->base,
> +			       &intelvipfb_drm_encoder_funcs,
> +			       DRM_MODE_ENCODER_VIRTUAL, NULL);
> +	if (ret)
> +		return ret;
> +
> +	drm_encoder_helper_add(&encoder->base,
> &intelvipfb_drm_encoder_helper);
> +
> +	conn = devm_kzalloc(drm->dev, sizeof(*conn), GFP_KERNEL);
> +	if (IS_ERR(conn))
> +		return PTR_ERR(conn);
> +
> +	ret = drm_connector_init(drm, conn,
> &intelvipfb_drm_connector_funcs,
> +				 DRM_MODE_CONNECTOR_DisplayPort);
> +	if (ret < 0) {
> +		dev_err(drm->dev, "failed to initialize drm
> connector\n");
> +		ret = -ENOMEM;
> +		goto error_encoder_cleanup;
> +	}
> +
> +	drm_connector_helper_add(conn,
> &intelvipfb_drm_connector_helper_funcs);
> +
> +	ret = drm_mode_connector_attach_encoder(conn, &encoder-
> >base);
> +	if (ret < 0) {
> +		dev_err(drm->dev, "could not attach connector to
> encoder\n");
> +		drm_connector_unregister(conn);
> +		goto error_connector_cleanup;
> +	}
> +
> +	return 0;
> +
> +error_connector_cleanup:
> +	drm_connector_cleanup(conn);
> +
> +error_encoder_cleanup:
> +	drm_encoder_cleanup(&encoder->base);
> +
> +	return ret;
> +}
> diff --git a/drivers/gpu/drm/ivip/intel_vip_core.c
> b/drivers/gpu/drm/ivip/intel_vip_core.c
> new file mode 100644
> index 0000000..3001ad0
> --- /dev/null
> +++ b/drivers/gpu/drm/ivip/intel_vip_core.c
> @@ -0,0 +1,215 @@
> +/*
> + * intel_vip_core.c -- Intel Video and Image Processing(VIP)
> + * Frame Buffer II driver
> + *
> + * This driver supports the Intel VIP Frame Reader component.
> + * More info on the hardware can be found in the Intel Video
> + * and Image Processing Suite User Guide at this address
> + * http://www.altera.com/literature/ug/ug_vip.pdf.
> + *
> + * 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.
> + *
> + * 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.
> + *
> + * Authors:
> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
> + *
> + */
> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_of.h>
> +
> +#include "intel_vip_drv.h"
> +
> +static const struct file_operations intelvipfb_drm_fops = {
> +	.owner		= THIS_MODULE,
> +	.open		= drm_open,
> +	.release	= drm_release,
> +	.unlocked_ioctl	= drm_ioctl,
> +	.poll		= drm_poll,
> +	.read		= drm_read,
> +	.llseek		= no_llseek,
> +	.mmap		= drm_gem_cma_mmap,
> +};
> +
> +static void intelvipfb_lastclose(struct drm_device *drm)
> +{
> +	struct intelvipfb_priv *fbpriv = drm->dev_private;
> +
> +	drm_fbdev_cma_restore_mode(fbpriv->fbcma);
> +}
> +
> +static struct drm_driver intelvipfb_drm = {
> +	.driver_features =
> +	    DRIVER_GEM | DRIVER_PRIME |
> +	    DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC,
> +	.gem_free_object_unlocked = drm_gem_cma_free_object,
> +	.gem_vm_ops = &drm_gem_cma_vm_ops,
> +	.dumb_create = drm_gem_cma_dumb_create,
> +	.dumb_map_offset = drm_gem_cma_dumb_map_offset,
> +	.dumb_destroy = drm_gem_dumb_destroy,
> +	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
> +	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
> +	.gem_prime_export = drm_gem_prime_export,
> +	.gem_prime_import = drm_gem_prime_import,
> +	.gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
> +	.gem_prime_import_sg_table =
> drm_gem_cma_prime_import_sg_table,
> +	.gem_prime_vmap = drm_gem_cma_prime_vmap,
> +	.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
> +	.gem_prime_mmap = drm_gem_cma_prime_mmap,
> +	.name = DRIVER_NAME,
> +	.date = "20170329",
> +	.desc = "Intel FPGA VIP SUITE",
> +	.major = 1,
> +	.minor = 0,
> +	.patchlevel = 0,
> +	.lastclose = intelvipfb_lastclose,
> +	.fops = &intelvipfb_drm_fops,
> +};
> +
> +static void intelvipfb_start_hw(void __iomem *base, resource_size_t
> addr)
> +{
> +	/*
> +	 * The frameinfo variable has to correspond to the size of
> the VIP Suite
> +	 * Frame Reader register 7 which will determine the maximum
> size used
> +	 * in this frameinfo
> +	 */
> +
> +	u32 frameinfo;
> +
> +	frameinfo =
> +		readl(base + INTELVIPFB_FRAME_READER) & 0x00ffffff;
> +
> +	writel(frameinfo, base + INTELVIPFB_FRAME_INFO);
> +
> +	writel(addr, base + INTELVIPFB_FRAME_START);
> +	/* Finally set the control register to 1 to start streaming
> */
> +	writel(1, base + INTELVIPFB_CONTROL);
> +}
> +
> +static void intelvipfb_disable_hw(void __iomem *base)
> +{
> +	/* set the control register to 0 to stop streaming */
> +	writel(0, base + INTELVIPFB_CONTROL);
> +}
> +
> +static void intelvipfb_output_poll_changed(struct drm_device *drm)
> +{
> +	struct intelvipfb_priv *fbpriv = drm->dev_private;
> +
> +	drm_fbdev_cma_hotplug_event(fbpriv->fbcma);
> +}
> +
> +static const struct drm_mode_config_funcs
> intelvipfb_mode_config_funcs = {
> +	.fb_create = drm_fb_cma_create,
> +	.output_poll_changed = intelvipfb_output_poll_changed,
> +	.atomic_check = drm_atomic_helper_check,
> +	.atomic_commit = drm_atomic_helper_commit,
> +};
> +
> +static struct drm_mode_config_helper_funcs
> intelvipfb_mode_config_helpers = {
> +	.atomic_commit_tail = drm_atomic_helper_commit_tail,
> +};
> +
> +static void intelvipfb_setup_mode_config(struct drm_device *drm,
> +					 struct fb_info *info)
> +{
> +	drm_mode_config_init(drm);
> +	drm->mode_config.min_width = 0;
> +	drm->mode_config.min_height = 0;
> +	drm->mode_config.max_width = info->var.xres;
> +	drm->mode_config.max_height = info->var.yres;
> +	drm->mode_config.preferred_depth = 32;
> +	drm->mode_config.funcs = &intelvipfb_mode_config_funcs;
> +	drm->mode_config.helper_private =
> &intelvipfb_mode_config_helpers;
> +}
> +
> +int intelvipfb_probe(struct device *dev, void __iomem *base)
> +{
> +	int retval;
> +	struct drm_device *drm;
> +	struct intelvipfb_priv *fbpriv = dev_get_drvdata(dev);
> +	struct fb_info *info = &fbpriv->info;
> +
> +	/*setup DRM */
> +	drm = drm_dev_alloc(&intelvipfb_drm, dev);
> +	if (IS_ERR(drm))
> +		return PTR_ERR(drm);
> +
> +	drm->dev_private = fbpriv;
> +
> +	dev_set_drvdata(dev, drm);
> +
> +	intelvipfb_setup_mode_config(drm, info);
> +
> +	retval = dma_set_mask_and_coherent(drm->dev,
> DMA_BIT_MASK(32));
> +	if (retval)
> +		return -ENODEV;
> +
> +	retval = intelvipfb_setup_crtc(drm);
> +	if (retval < 0)
> +		return -ENODEV;
> +
> +	retval = intelvipfb_drm_conn_init(drm);
> +	if (retval)
> +		return -ENOMEM;
> +
> +	drm_mode_config_reset(drm);
> +
> +	fbpriv->fbcma = drm_fbdev_cma_init(drm, PREF_BPP,
> +							CRTC_NUM,
> CONN_NUM);
> +	if (!fbpriv->fbcma) {
> +		fbpriv->fbcma = NULL;
> +		return -ENODEV;
> +	}
> +
> +	intelvipfb_start_hw(base, drm->mode_config.fb_base);
> +
> +	drm_kms_helper_poll_init(drm);
> +
> +	drm_dev_register(drm, 0);
> +
> +	return retval;
> +}
> +EXPORT_SYMBOL_GPL(intelvipfb_probe);
> +
> +int intelvipfb_remove(struct device *dev)
> +{
> +	struct drm_device *drm = dev_get_drvdata(dev);
> +	struct intelvipfb_priv *fbpriv = drm->dev_private;
> +
> +	drm_dev_unregister(drm);
> +
> +	drm_kms_helper_poll_fini(drm);
> +	drm_fbdev_cma_fini(fbpriv->fbcma);
> +
> +	intelvipfb_disable_hw(fbpriv->base);
> +
> +drm_mode_config_cleanup(drm);
> +
> +drm_dev_unref(drm);
> +
> +devm_kfree(dev, fbpriv);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(intelvipfb_remove);
> +
> +MODULE_AUTHOR("Ong, Hean-Loong <hean.loong.ong@intel.com>");
> +MODULE_DESCRIPTION("Intel VIP Frame Buffer II driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/gpu/drm/ivip/intel_vip_crtc.c
> b/drivers/gpu/drm/ivip/intel_vip_crtc.c
> new file mode 100644
> index 0000000..97a3954
> --- /dev/null
> +++ b/drivers/gpu/drm/ivip/intel_vip_crtc.c
> @@ -0,0 +1,161 @@
> +/*
> + * intel_vip_crtc.c -- Intel Video and Image Processing(VIP)
> + * Frame Buffer II driver
> + *
> + * This driver supports the Intel VIP Frame Reader component.
> + * More info on the hardware can be found in the Intel Video
> + * and Image Processing Suite User Guide at this address
> + * http://www.altera.com/literature/ug/ug_vip.pdf.
> + *
> + * 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.
> + *
> + * 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.
> + *
> + * Authors:
> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
> + *
> + */
> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/platform_data/simplefb.h>
> +
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_plane_helper.h>
> +
> +#include "intel_vip_drv.h"
> +
> +static struct simplefb_format intelvipfb_formats[] =
> SIMPLEFB_FORMATS;
> +
> +static void intelvipfb_crtc_destroy(struct drm_crtc *crtc)
> +{
> +	drm_crtc_cleanup(crtc);
> +	kfree(crtc);
> +}
> +
> +static const struct drm_crtc_funcs intelvipfb_crtc_funcs = {
> +	.destroy = intelvipfb_crtc_destroy,
> +	.set_config = drm_atomic_helper_set_config,
> +	.page_flip = drm_atomic_helper_page_flip,
> +	.reset = drm_atomic_helper_crtc_reset,
> +	.atomic_duplicate_state =
> drm_atomic_helper_crtc_duplicate_state,
> +	.atomic_destroy_state =
> drm_atomic_helper_crtc_destroy_state,
> +};
> +
> +static void intelvipfb_crtc_atomic_begin(struct drm_crtc *crtc,
> +					 struct drm_crtc_state
> *state)
> +{
> +	struct drm_pending_vblank_event *event = crtc->state->event;
> +
> +	if (event) {
> +		crtc->state->event = NULL;
> +
> +		spin_lock_irq(&crtc->dev->event_lock);
> +		drm_crtc_send_vblank_event(crtc, event);
> +		spin_unlock_irq(&crtc->dev->event_lock);
> +	}
> +}
> +
> +static void intelvipfb_crtc_nop(struct drm_crtc *crtc)
> +{
> +	/* do nothing */;
> +}
> +
> +static const struct drm_crtc_helper_funcs
> intelvipfb_crtc_helper_funcs = {
> +	.atomic_begin	= intelvipfb_crtc_atomic_begin,
> +	.enable = intelvipfb_crtc_nop,
> +};
> +
> +static void intelvipfb_plane_destroy(struct drm_plane *plane)
> +{
> +	drm_plane_helper_disable(plane);
> +	drm_plane_cleanup(plane);
> +}
> +
> +static const struct drm_plane_funcs intelvipfb_plane_funcs = {
> +	.update_plane		=
> drm_atomic_helper_update_plane,
> +	.disable_plane		=
> drm_atomic_helper_disable_plane,
> +	.destroy		= intelvipfb_plane_destroy,
> +	.reset			=
> drm_atomic_helper_plane_reset,
> +	.atomic_duplicate_state =
> drm_atomic_helper_plane_duplicate_state,
> +	.atomic_destroy_state	=
> drm_atomic_helper_plane_destroy_state,
> +};
> +
> +static void intelvipfb_plane_atomic_update(struct drm_plane *plane,
> +					   struct drm_plane_state
> *state)
> +{
> +	struct intelvipfb_priv *fbpriv;
> +	struct drm_gem_cma_object *gem;
> +
> +	if (!plane->state->crtc || !plane->state->fb)
> +		return;
> +
> +	fbpriv = plane->dev->dev_private;
> +	gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
> +	writel(gem->paddr, fbpriv->base + INTELVIPFB_FRAME_START);
> +}
> +
> +static const struct drm_plane_helper_funcs
> intelvipfb_plane_helper_funcs = {
> +	.atomic_update = intelvipfb_plane_atomic_update,
> +};
> +
> +static struct drm_plane *intelvipfb_plane_init(struct drm_device
> *drm)
> +{
> +	struct drm_plane *plane = NULL;
> +	u32 formats[ARRAY_SIZE(intelvipfb_formats)], i;
> +	int ret;
> +
> +	plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
> +	if (!plane)
> +		return ERR_PTR(-ENOMEM);
> +
> +	for (i = 0; i < ARRAY_SIZE(intelvipfb_formats); i++)
> +		formats[i] = intelvipfb_formats[i].fourcc;
> +
> +	ret = drm_universal_plane_init(drm, plane, 0xff,
> +				       &intelvipfb_plane_funcs,
> +				       formats, ARRAY_SIZE(formats),
> +				       DRM_PLANE_TYPE_PRIMARY,
> NULL);
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	drm_plane_helper_add(plane, &intelvipfb_plane_helper_funcs);
> +
> +	return plane;
> +}
> +
> +int intelvipfb_setup_crtc(struct drm_device *drm)
> +{
> +	struct drm_crtc *crtc;
> +	struct drm_plane *primary;
> +	int ret;
> +
> +	crtc = kzalloc(sizeof(*crtc), GFP_KERNEL);
> +	if (!crtc)
> +		return -ENOMEM;
> +
> +	primary = intelvipfb_plane_init(drm);
> +	if (IS_ERR(primary))
> +		return PTR_ERR(primary);
> +
> +	ret = drm_crtc_init_with_planes(drm, crtc, primary, NULL,
> +					&intelvipfb_crtc_funcs,
> NULL);
> +
> +	if (ret) {
> +		intelvipfb_plane_destroy(primary);
> +		return ret;
> +	}
> +
> +	drm_crtc_helper_add(crtc, &intelvipfb_crtc_helper_funcs);
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/ivip/intel_vip_drv.h
> b/drivers/gpu/drm/ivip/intel_vip_drv.h
> new file mode 100644
> index 0000000..657f23c
> --- /dev/null
> +++ b/drivers/gpu/drm/ivip/intel_vip_drv.h
> @@ -0,0 +1,55 @@
> +/*
> + * Copyright (C) 2017 Intel Corporation.
> + *
> + * Intel Video and Image Processing(VIP) Frame Buffer II driver.
> + *
> + * 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.
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License
> along with
> + * this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authors:
> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
> + *
> + */
> +#ifndef _INTEL_VIP_DRV_H
> +#define _INTEL_VIP_DRV_H
> +#include <linux/io.h>
> +#include <linux/fb.h>
> +
> +#define DRIVER_NAME	"intelvipfb"
> +#define BYTES_PER_PIXEL	4
> +#define PREF_BPP		32
> +#define CRTC_NUM		1
> +#define CONN_NUM		1
> +
> +/* control registers */
> +#define INTELVIPFB_CONTROL		0
> +#define INTELVIPFB_STATUS		0x4
> +#define INTELVIPFB_INTERRUPT		0x8
> +#define INTELVIPFB_FRAME_COUNTER	0xC
> +#define INTELVIPFB_FRAME_DROP		0x10
> +#define INTELVIPFB_FRAME_INFO		0x14
> +#define INTELVIPFB_FRAME_START		0x18
> +#define INTELVIPFB_FRAME_READER		0x1C
> +
> +int intelvipfb_probe(struct device *dev, void __iomem *base);
> +int intelvipfb_remove(struct device *dev);
> +int intelvipfb_setup_crtc(struct drm_device *drm);
> +int intelvipfb_drm_conn_init(struct drm_device *drm);
> +
> +struct intelvipfb_priv {
> +	struct drm_fbdev_cma *fbcma;
> +	struct drm_device *drm;
> +	struct fb_info info;
> +	void	__iomem		*base;
> +};
> +
> +#endif
> diff --git a/drivers/gpu/drm/ivip/intel_vip_of.c
> b/drivers/gpu/drm/ivip/intel_vip_of.c
> new file mode 100644
> index 0000000..17dff36
> --- /dev/null
> +++ b/drivers/gpu/drm/ivip/intel_vip_of.c
> @@ -0,0 +1,146 @@
> +/*
> + * intel_vip_of.c -- Intel Video and Image Processing(VIP)
> + * Frame Buffer II driver
> + *
> + * This driver supports the Intel VIP Frame Reader component.
> + * More info on the hardware can be found in the Intel Video
> + * and Image Processing Suite User Guide at this address
> + * http://www.altera.com/literature/ug/ug_vip.pdf.
> + *
> + * 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.
> + *
> + * 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.
> + *
> + * Authors:
> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
> + *
> + */
> +
> +#include <linux/fb.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +
> +#include <drm/drm_fb_helper.h>
> +#include "intel_vip_drv.h"
> +
> +/*
> + * Setting up information derived from OF Device Tree Nodes
> + * max-width, max-height, bits per pixel, memory port width
> + */
> +
> +static int intelvipfb_of_setup(struct intelvipfb_priv *fbdata,
> +			       struct platform_device *pdev)
> +{
> +	int ret;
> +	int mem_word_width;
> +	u32 bits_per_color;
> +	struct device_node *np = pdev->dev.of_node;
> +
> +	ret = of_property_read_u32(np, "altr,max-width",
> +				   &fbdata->info.var.xres);
> +	if (ret) {
> +		dev_err(&pdev->dev,
> +			"Missing required parameter 'altr,max-
> width'");
> +		return ret;
> +	}
> +	fbdata->info.var.xres_virtual = fbdata->info.var.xres;
> +
> +	ret = of_property_read_u32(np, "altr,max-height",
> +				   &fbdata->info.var.yres);
> +	if (ret) {
> +		dev_err(&pdev->dev,
> +			"Missing required parameter 'altr,max-
> height'");
> +		return ret;
> +	}
> +	fbdata->info.var.yres_virtual = fbdata->info.var.yres;
> +
> +	ret = of_property_read_u32(np, "altr,bits-per-symbol",
> &bits_per_color);
> +	if (ret) {
> +		dev_err(&pdev->dev,
> +			"Missing required parameter 'altr,bits-per-
> symbol'");
> +		return ret;
> +	}
> +
> +	fbdata->info.var.bits_per_pixel = bits_per_color *
> BYTES_PER_PIXEL;
> +
> +	ret = of_property_read_u32(np, "altr,mem-port-width",
> &mem_word_width);
> +	if (ret) {
> +		dev_err(&pdev->dev,
> +			"Missing required parameter 'altr,mem-port-
> width '");
> +		return ret;
> +	}
> +
> +	if (!(mem_word_width >= 32 && mem_word_width % 32 == 0)) {
> +		dev_err(&pdev->dev,
> +			"mem-word-width is set to %i. must be >= 32
> and multiple of 32.",
> +			 mem_word_width);
> +		return -ENODEV;
> +	}
> +
> +	return 0;
> +}
> +
> +static int intelvipfb_of_probe(struct platform_device *pdev)
> +{
> +	int retval;
> +	struct resource *reg_res;
> +	struct intelvipfb_priv *fbdata;
> +
> +	fbdata = devm_kzalloc(&pdev->dev, sizeof(*fbdata),
> GFP_KERNEL);
> +	if (!fbdata)
> +		return -ENOMEM;
> +
> +	reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!reg_res)
> +		return -ENOMEM;
> +
> +	fbdata->base = devm_ioremap_resource(&pdev->dev, reg_res);
> +
> +	if (IS_ERR(fbdata->base)) {
> +		dev_err(&pdev->dev, "devm_ioremap_resource
> failed\n");
> +		retval = PTR_ERR(fbdata->base);
> +		return -ENOMEM;
> +	}
> +
> +	intelvipfb_of_setup(fbdata, pdev);
> +
> +	platform_set_drvdata(pdev, fbdata);
> +
> +	return intelvipfb_probe(&pdev->dev, fbdata->base);
> +}
> +
> +static int intelvipfb_of_remove(struct platform_device *pdev)
> +{
> +	return intelvipfb_remove(&pdev->dev);
> +}
> +
> +/*
> + * The name vip-frame-buffer-2.0 is derived from
> + * http://www.altera.com/literature/ug/ug_vip.pdf
> + * frame buffer IP cores section 14
> + */
> +
> +static const struct of_device_id intelvipfb_of_match[] = {
> +	{ .compatible = "altr,vip-frame-buffer-2.0" },
> +	{},
> +};
> +
> +MODULE_DEVICE_TABLE(of, intelvipfb_of_match);
> +
> +static struct platform_driver intelvipfb_driver = {
> +	.probe = intelvipfb_of_probe,
> +	.remove = intelvipfb_of_remove,
> +	.driver = {
> +		.name = DRIVER_NAME,
> +		.of_match_table = intelvipfb_of_match,
> +	},
> +};
> +
> +module_platform_driver(intelvipfb_driver);
> -- 
> 1.7.1
> 
> 
> -----Original Message-----
> From: Ong, Hean Loong 
> Sent: Friday, March 31, 2017 5:09 PM
> To: Vetter, Daniel <daniel.vetter@intel.com>; airlied@linux.ie
> Cc: dri-devel@lists.freedesktop.org
> Subject: DRM Display driver for Intel FPGA Video and Image Processing
> Suite
> 
> Hi,
> 
> I would like to upstream the attached Intel FPGA Video and Image
> Processing Suite. The attached patch supports the Intel Arria10
> devkit and its variants. The purpose of the patch is to enable the
> FPGA driven display designed from the Intel Quartus FPGA design
> suite.
> 
> The driver is required as part of the Intel Arria10 devkit reference
> design. The driver was tested on:
> - The Open Embedded Angstrom Distro.
> - The matchbox-terminal and window-manager was used for functional
> testing
> 
> Current the intention of the driver is meant to validate the FPGA
> designs on the Arria10 devkit for Display Port connecter. We have not
> verified its performance of or stability in 3D acceleration or other
> non Intel FPGA hardware
> 
> BR
> 
> Hean Loong
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: DRM Display driver for Intel FPGA Video and Image Processing Suite
  2017-04-06  6:29   ` Ong, Hean Loong
@ 2017-04-07 16:31     ` Daniel Vetter
  2017-04-08  5:41       ` Ong, Hean Loong
  0 siblings, 1 reply; 9+ messages in thread
From: Daniel Vetter @ 2017-04-07 16:31 UTC (permalink / raw)
  To: Ong, Hean Loong; +Cc: Vetter, Daniel, dri-devel

On Thu, Apr 6, 2017 at 8:29 AM, Ong, Hean Loong
<hean.loong.ong@intel.com> wrote:
> Hi All,
>
> Any comments for the patch below?

Seems the same version that I already reviewed. My comment about not
sending inline was more for the next version, especially once it's
about applying the patch, attached patches are a bit of a pain (since
they break the tooling here).
-Daniel
>
> Thanks
>
> Hean Loong
>
> On Tue, 2017-04-04 at 04:01 +0000, Ong, Hean Loong wrote:
>> Hi All,
>>
>> Apologies for the attachment earlier. Below are the inline changes
>> for the patch
>>
>> From 0de293e3646a1780ed603cf8e1f2a19d9aebbe83 Mon Sep 17 00:00:00
>> 2001
>> From: Ong, Hean Loong <hean.loong.ong@intel.com>
>> Date: Thu, 30 Mar 2017 18:02:22 +0800
>> Subject: [PATCHv0] Intel FPGA Video and Image Processing Suite Frame
>> Buffer II driver
>>
>> Signed-off-by: Ong, Hean Loong <hean.loong.ong@intel.com>
>> ---
>>  drivers/gpu/drm/Kconfig               |    2 +
>>  drivers/gpu/drm/Makefile              |    1 +
>>  drivers/gpu/drm/ivip/Kconfig          |   22 ++++
>>  drivers/gpu/drm/ivip/Makefile         |    9 ++
>>  drivers/gpu/drm/ivip/intel_vip_conn.c |  145 ++++++++++++++++++++++
>>  drivers/gpu/drm/ivip/intel_vip_core.c |  215
>> +++++++++++++++++++++++++++++++++
>>  drivers/gpu/drm/ivip/intel_vip_crtc.c |  161
>> ++++++++++++++++++++++++
>>  drivers/gpu/drm/ivip/intel_vip_drv.h  |   55 +++++++++
>>  drivers/gpu/drm/ivip/intel_vip_of.c   |  146 ++++++++++++++++++++++
>>  9 files changed, 756 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/gpu/drm/ivip/Kconfig
>>  create mode 100644 drivers/gpu/drm/ivip/Makefile
>>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_conn.c
>>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_core.c
>>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_crtc.c
>>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_drv.h
>>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_of.c
>>
>> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
>> index ebfe840..c487507 100644
>> --- a/drivers/gpu/drm/Kconfig
>> +++ b/drivers/gpu/drm/Kconfig
>> @@ -167,6 +167,8 @@ source "drivers/gpu/drm/nouveau/Kconfig"
>>
>>  source "drivers/gpu/drm/i915/Kconfig"
>>
>> +source "drivers/gpu/drm/ivip/Kconfig"
>> +
>>  config DRM_VGEM
>>       tristate "Virtual GEM provider"
>>       depends on DRM
>> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
>> index b9ae428..945cf53 100644
>> --- a/drivers/gpu/drm/Makefile
>> +++ b/drivers/gpu/drm/Makefile
>> @@ -52,6 +52,7 @@ obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/
>>  obj-$(CONFIG_DRM_MGA)        += mga/
>>  obj-$(CONFIG_DRM_I810)       += i810/
>>  obj-$(CONFIG_DRM_I915)       += i915/
>> +obj-$(CONFIG_DRM_IVIP)       += ivip/
>>  obj-$(CONFIG_DRM_MGAG200) += mgag200/
>>  obj-$(CONFIG_DRM_VC4)  += vc4/
>>  obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus/
>> diff --git a/drivers/gpu/drm/ivip/Kconfig
>> b/drivers/gpu/drm/ivip/Kconfig
>> new file mode 100644
>> index 0000000..ddf3cb5
>> --- /dev/null
>> +++ b/drivers/gpu/drm/ivip/Kconfig
>> @@ -0,0 +1,22 @@
>> +config DRM_IVIP
>> +        tristate "Intel FGPA Video and Image Processing"
>> +        depends on DRM
>> +        select DRM_GEM_CMA_HELPER
>> +        select DRM_KMS_HELPER
>> +        select DRM_KMS_FB_HELPER
>> +        select DRM_KMS_CMA_HELPER
>> +        help
>> +                Choose this option if you have a Intel FPGA Arria 10
>> system
>> +                and above with a Display Port IP. This does not
>> support legacy
>> +                Intel FPGA Cyclone V display port. Currently only
>> single frame
>> +                buffer is supported. Note that ACPI and X_86
>> architecture is yet
>> +                to be supported.
>> +
>> +config DRM_IVIP_OF
>> +        tristate "Intel FGPA Video and Image Processing Open
>> Firmware Systems"
>> +        depends on DRM_IVIP && OF
>> +        help
>> +                Choose this option if the Intel FPGA system is using
>> Open
>> +                Firmware systems (Arria 10). If M is selected the
>> module would
>> +                be called ivip.
>> +
>> diff --git a/drivers/gpu/drm/ivip/Makefile
>> b/drivers/gpu/drm/ivip/Makefile
>> new file mode 100644
>> index 0000000..7be1e99
>> --- /dev/null
>> +++ b/drivers/gpu/drm/ivip/Makefile
>> @@ -0,0 +1,9 @@
>> +#
>> +# Makefile for the drm device driver.  This driver provides support
>> for the
>> +# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
>> +
>> +ccflags-y := -Iinclude/drm
>> +
>> +obj-$(CONFIG_DRM_IVIP_OF) += ivip.o
>> +ivip-objs := intel_vip_of.o intel_vip_core.o \
>> +intel_vip_conn.o intel_vip_crtc.o
>> diff --git a/drivers/gpu/drm/ivip/intel_vip_conn.c
>> b/drivers/gpu/drm/ivip/intel_vip_conn.c
>> new file mode 100644
>> index 0000000..89ab587
>> --- /dev/null
>> +++ b/drivers/gpu/drm/ivip/intel_vip_conn.c
>> @@ -0,0 +1,145 @@
>> +/*
>> + * intel_vip_conn.c -- Intel Video and Image Processing(VIP)
>> + * Frame Buffer II driver
>> + *
>> + * This driver supports the Intel VIP Frame Reader component.
>> + * More info on the hardware can be found in the Intel Video
>> + * and Image Processing Suite User Guide at this address
>> + * http://www.altera.com/literature/ug/ug_vip.pdf.
>> + *
>> + * 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.
>> + *
>> + * 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.
>> + *
>> + * Authors:
>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>> + *
>> + */
>> +
>> +#include <linux/init.h>
>> +#include <linux/kernel.h>
>> +#include <drm/drm_atomic_helper.h>
>> +#include <drm/drm_crtc_helper.h>
>> +#include <drm/drm_encoder_slave.h>
>> +#include <drm/drm_plane_helper.h>
>> +
>> +static enum drm_connector_status
>> +intelvipfb_drm_connector_detect(struct drm_connector *connector,
>> bool force)
>> +{
>> +     return connector_status_connected;
>> +}
>> +
>> +static void intelvipfb_drm_connector_destroy(struct drm_connector
>> *connector)
>> +{
>> +     drm_connector_unregister(connector);
>> +     drm_connector_cleanup(connector);
>> +}
>> +
>> +static const struct drm_connector_funcs
>> intelvipfb_drm_connector_funcs = {
>> +     .dpms = drm_helper_connector_dpms,
>> +     .reset = drm_atomic_helper_connector_reset,
>> +     .detect = intelvipfb_drm_connector_detect,
>> +     .fill_modes = drm_helper_probe_single_connector_modes,
>> +     .destroy = intelvipfb_drm_connector_destroy,
>> +     .atomic_duplicate_state =
>> drm_atomic_helper_connector_duplicate_state,
>> +     .atomic_destroy_state =
>> drm_atomic_helper_connector_destroy_state,
>> +};
>> +
>> +static int intelvipfb_drm_connector_get_modes(struct drm_connector
>> *connector)
>> +{
>> +     struct drm_device *drm = connector->dev;
>> +     int count;
>> +
>> +     count = drm_add_modes_noedid(connector, drm-
>> >mode_config.max_width,
>> +                                  drm->mode_config.max_height);
>> +     drm_set_preferred_mode(connector, drm-
>> >mode_config.max_width,
>> +                            drm->mode_config.max_height);
>> +     return count;
>> +}
>> +
>> +static const struct drm_connector_helper_funcs
>> +intelvipfb_drm_connector_helper_funcs = {
>> +     .get_modes = intelvipfb_drm_connector_get_modes,
>> +};
>> +
>> +static const struct drm_encoder_funcs
>> +intelvipfb_drm_encoder_funcs = {
>> +     .destroy = drm_encoder_cleanup,
>> +};
>> +
>> +static void intelvipfb_mode_set(struct drm_encoder *encoder,
>> +                             struct drm_display_mode *mode,
>> +                             struct drm_display_mode
>> *adjusted_mode)
>> +{
>> +     /* do nothing */
>> +}
>> +
>> +static void intelvipfb_nop(struct drm_encoder *encoder)
>> +{
>> +     /* do nothing */
>> +}
>> +
>> +static const struct drm_encoder_helper_funcs i
>> +intelvipfb_drm_encoder_helper = {
>> +     .mode_set = intelvipfb_mode_set,
>> +     .enable = intelvipfb_nop,
>> +     .disable = intelvipfb_nop,
>> +};
>> +
>> +int intelvipfb_drm_conn_init(struct drm_device *drm)
>> +{
>> +     struct drm_encoder_slave *encoder;
>> +     struct drm_connector *conn;
>> +     int ret;
>> +
>> +     encoder = devm_kzalloc(drm->dev, sizeof(*encoder),
>> GFP_KERNEL);
>> +     if (!encoder)
>> +             return -ENOMEM;
>> +
>> +     encoder->base.possible_crtcs = 1;
>> +     encoder->base.possible_clones = 0;
>> +
>> +     ret = drm_encoder_init(drm, &encoder->base,
>> +                            &intelvipfb_drm_encoder_funcs,
>> +                            DRM_MODE_ENCODER_VIRTUAL, NULL);
>> +     if (ret)
>> +             return ret;
>> +
>> +     drm_encoder_helper_add(&encoder->base,
>> &intelvipfb_drm_encoder_helper);
>> +
>> +     conn = devm_kzalloc(drm->dev, sizeof(*conn), GFP_KERNEL);
>> +     if (IS_ERR(conn))
>> +             return PTR_ERR(conn);
>> +
>> +     ret = drm_connector_init(drm, conn,
>> &intelvipfb_drm_connector_funcs,
>> +                              DRM_MODE_CONNECTOR_DisplayPort);
>> +     if (ret < 0) {
>> +             dev_err(drm->dev, "failed to initialize drm
>> connector\n");
>> +             ret = -ENOMEM;
>> +             goto error_encoder_cleanup;
>> +     }
>> +
>> +     drm_connector_helper_add(conn,
>> &intelvipfb_drm_connector_helper_funcs);
>> +
>> +     ret = drm_mode_connector_attach_encoder(conn, &encoder-
>> >base);
>> +     if (ret < 0) {
>> +             dev_err(drm->dev, "could not attach connector to
>> encoder\n");
>> +             drm_connector_unregister(conn);
>> +             goto error_connector_cleanup;
>> +     }
>> +
>> +     return 0;
>> +
>> +error_connector_cleanup:
>> +     drm_connector_cleanup(conn);
>> +
>> +error_encoder_cleanup:
>> +     drm_encoder_cleanup(&encoder->base);
>> +
>> +     return ret;
>> +}
>> diff --git a/drivers/gpu/drm/ivip/intel_vip_core.c
>> b/drivers/gpu/drm/ivip/intel_vip_core.c
>> new file mode 100644
>> index 0000000..3001ad0
>> --- /dev/null
>> +++ b/drivers/gpu/drm/ivip/intel_vip_core.c
>> @@ -0,0 +1,215 @@
>> +/*
>> + * intel_vip_core.c -- Intel Video and Image Processing(VIP)
>> + * Frame Buffer II driver
>> + *
>> + * This driver supports the Intel VIP Frame Reader component.
>> + * More info on the hardware can be found in the Intel Video
>> + * and Image Processing Suite User Guide at this address
>> + * http://www.altera.com/literature/ug/ug_vip.pdf.
>> + *
>> + * 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.
>> + *
>> + * 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.
>> + *
>> + * Authors:
>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>> + *
>> + */
>> +
>> +#include <linux/init.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +
>> +#include <drm/drmP.h>
>> +#include <drm/drm_atomic.h>
>> +#include <drm/drm_atomic_helper.h>
>> +#include <drm/drm_crtc_helper.h>
>> +#include <drm/drm_fb_helper.h>
>> +#include <drm/drm_fb_cma_helper.h>
>> +#include <drm/drm_gem_cma_helper.h>
>> +#include <drm/drm_of.h>
>> +
>> +#include "intel_vip_drv.h"
>> +
>> +static const struct file_operations intelvipfb_drm_fops = {
>> +     .owner          = THIS_MODULE,
>> +     .open           = drm_open,
>> +     .release        = drm_release,
>> +     .unlocked_ioctl = drm_ioctl,
>> +     .poll           = drm_poll,
>> +     .read           = drm_read,
>> +     .llseek         = no_llseek,
>> +     .mmap           = drm_gem_cma_mmap,
>> +};
>> +
>> +static void intelvipfb_lastclose(struct drm_device *drm)
>> +{
>> +     struct intelvipfb_priv *fbpriv = drm->dev_private;
>> +
>> +     drm_fbdev_cma_restore_mode(fbpriv->fbcma);
>> +}
>> +
>> +static struct drm_driver intelvipfb_drm = {
>> +     .driver_features =
>> +         DRIVER_GEM | DRIVER_PRIME |
>> +         DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC,
>> +     .gem_free_object_unlocked = drm_gem_cma_free_object,
>> +     .gem_vm_ops = &drm_gem_cma_vm_ops,
>> +     .dumb_create = drm_gem_cma_dumb_create,
>> +     .dumb_map_offset = drm_gem_cma_dumb_map_offset,
>> +     .dumb_destroy = drm_gem_dumb_destroy,
>> +     .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
>> +     .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
>> +     .gem_prime_export = drm_gem_prime_export,
>> +     .gem_prime_import = drm_gem_prime_import,
>> +     .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
>> +     .gem_prime_import_sg_table =
>> drm_gem_cma_prime_import_sg_table,
>> +     .gem_prime_vmap = drm_gem_cma_prime_vmap,
>> +     .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
>> +     .gem_prime_mmap = drm_gem_cma_prime_mmap,
>> +     .name = DRIVER_NAME,
>> +     .date = "20170329",
>> +     .desc = "Intel FPGA VIP SUITE",
>> +     .major = 1,
>> +     .minor = 0,
>> +     .patchlevel = 0,
>> +     .lastclose = intelvipfb_lastclose,
>> +     .fops = &intelvipfb_drm_fops,
>> +};
>> +
>> +static void intelvipfb_start_hw(void __iomem *base, resource_size_t
>> addr)
>> +{
>> +     /*
>> +      * The frameinfo variable has to correspond to the size of
>> the VIP Suite
>> +      * Frame Reader register 7 which will determine the maximum
>> size used
>> +      * in this frameinfo
>> +      */
>> +
>> +     u32 frameinfo;
>> +
>> +     frameinfo =
>> +             readl(base + INTELVIPFB_FRAME_READER) & 0x00ffffff;
>> +
>> +     writel(frameinfo, base + INTELVIPFB_FRAME_INFO);
>> +
>> +     writel(addr, base + INTELVIPFB_FRAME_START);
>> +     /* Finally set the control register to 1 to start streaming
>> */
>> +     writel(1, base + INTELVIPFB_CONTROL);
>> +}
>> +
>> +static void intelvipfb_disable_hw(void __iomem *base)
>> +{
>> +     /* set the control register to 0 to stop streaming */
>> +     writel(0, base + INTELVIPFB_CONTROL);
>> +}
>> +
>> +static void intelvipfb_output_poll_changed(struct drm_device *drm)
>> +{
>> +     struct intelvipfb_priv *fbpriv = drm->dev_private;
>> +
>> +     drm_fbdev_cma_hotplug_event(fbpriv->fbcma);
>> +}
>> +
>> +static const struct drm_mode_config_funcs
>> intelvipfb_mode_config_funcs = {
>> +     .fb_create = drm_fb_cma_create,
>> +     .output_poll_changed = intelvipfb_output_poll_changed,
>> +     .atomic_check = drm_atomic_helper_check,
>> +     .atomic_commit = drm_atomic_helper_commit,
>> +};
>> +
>> +static struct drm_mode_config_helper_funcs
>> intelvipfb_mode_config_helpers = {
>> +     .atomic_commit_tail = drm_atomic_helper_commit_tail,
>> +};
>> +
>> +static void intelvipfb_setup_mode_config(struct drm_device *drm,
>> +                                      struct fb_info *info)
>> +{
>> +     drm_mode_config_init(drm);
>> +     drm->mode_config.min_width = 0;
>> +     drm->mode_config.min_height = 0;
>> +     drm->mode_config.max_width = info->var.xres;
>> +     drm->mode_config.max_height = info->var.yres;
>> +     drm->mode_config.preferred_depth = 32;
>> +     drm->mode_config.funcs = &intelvipfb_mode_config_funcs;
>> +     drm->mode_config.helper_private =
>> &intelvipfb_mode_config_helpers;
>> +}
>> +
>> +int intelvipfb_probe(struct device *dev, void __iomem *base)
>> +{
>> +     int retval;
>> +     struct drm_device *drm;
>> +     struct intelvipfb_priv *fbpriv = dev_get_drvdata(dev);
>> +     struct fb_info *info = &fbpriv->info;
>> +
>> +     /*setup DRM */
>> +     drm = drm_dev_alloc(&intelvipfb_drm, dev);
>> +     if (IS_ERR(drm))
>> +             return PTR_ERR(drm);
>> +
>> +     drm->dev_private = fbpriv;
>> +
>> +     dev_set_drvdata(dev, drm);
>> +
>> +     intelvipfb_setup_mode_config(drm, info);
>> +
>> +     retval = dma_set_mask_and_coherent(drm->dev,
>> DMA_BIT_MASK(32));
>> +     if (retval)
>> +             return -ENODEV;
>> +
>> +     retval = intelvipfb_setup_crtc(drm);
>> +     if (retval < 0)
>> +             return -ENODEV;
>> +
>> +     retval = intelvipfb_drm_conn_init(drm);
>> +     if (retval)
>> +             return -ENOMEM;
>> +
>> +     drm_mode_config_reset(drm);
>> +
>> +     fbpriv->fbcma = drm_fbdev_cma_init(drm, PREF_BPP,
>> +                                                     CRTC_NUM,
>> CONN_NUM);
>> +     if (!fbpriv->fbcma) {
>> +             fbpriv->fbcma = NULL;
>> +             return -ENODEV;
>> +     }
>> +
>> +     intelvipfb_start_hw(base, drm->mode_config.fb_base);
>> +
>> +     drm_kms_helper_poll_init(drm);
>> +
>> +     drm_dev_register(drm, 0);
>> +
>> +     return retval;
>> +}
>> +EXPORT_SYMBOL_GPL(intelvipfb_probe);
>> +
>> +int intelvipfb_remove(struct device *dev)
>> +{
>> +     struct drm_device *drm = dev_get_drvdata(dev);
>> +     struct intelvipfb_priv *fbpriv = drm->dev_private;
>> +
>> +     drm_dev_unregister(drm);
>> +
>> +     drm_kms_helper_poll_fini(drm);
>> +     drm_fbdev_cma_fini(fbpriv->fbcma);
>> +
>> +     intelvipfb_disable_hw(fbpriv->base);
>> +
>> +drm_mode_config_cleanup(drm);
>> +
>> +drm_dev_unref(drm);
>> +
>> +devm_kfree(dev, fbpriv);
>> +
>> +     return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(intelvipfb_remove);
>> +
>> +MODULE_AUTHOR("Ong, Hean-Loong <hean.loong.ong@intel.com>");
>> +MODULE_DESCRIPTION("Intel VIP Frame Buffer II driver");
>> +MODULE_LICENSE("GPL v2");
>> diff --git a/drivers/gpu/drm/ivip/intel_vip_crtc.c
>> b/drivers/gpu/drm/ivip/intel_vip_crtc.c
>> new file mode 100644
>> index 0000000..97a3954
>> --- /dev/null
>> +++ b/drivers/gpu/drm/ivip/intel_vip_crtc.c
>> @@ -0,0 +1,161 @@
>> +/*
>> + * intel_vip_crtc.c -- Intel Video and Image Processing(VIP)
>> + * Frame Buffer II driver
>> + *
>> + * This driver supports the Intel VIP Frame Reader component.
>> + * More info on the hardware can be found in the Intel Video
>> + * and Image Processing Suite User Guide at this address
>> + * http://www.altera.com/literature/ug/ug_vip.pdf.
>> + *
>> + * 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.
>> + *
>> + * 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.
>> + *
>> + * Authors:
>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>> + *
>> + */
>> +
>> +#include <linux/init.h>
>> +#include <linux/kernel.h>
>> +#include <linux/platform_data/simplefb.h>
>> +
>> +#include <drm/drm_atomic.h>
>> +#include <drm/drm_atomic_helper.h>
>> +#include <drm/drm_crtc.h>
>> +#include <drm/drm_crtc_helper.h>
>> +#include <drm/drm_fb_cma_helper.h>
>> +#include <drm/drm_gem_cma_helper.h>
>> +#include <drm/drm_plane_helper.h>
>> +
>> +#include "intel_vip_drv.h"
>> +
>> +static struct simplefb_format intelvipfb_formats[] =
>> SIMPLEFB_FORMATS;
>> +
>> +static void intelvipfb_crtc_destroy(struct drm_crtc *crtc)
>> +{
>> +     drm_crtc_cleanup(crtc);
>> +     kfree(crtc);
>> +}
>> +
>> +static const struct drm_crtc_funcs intelvipfb_crtc_funcs = {
>> +     .destroy = intelvipfb_crtc_destroy,
>> +     .set_config = drm_atomic_helper_set_config,
>> +     .page_flip = drm_atomic_helper_page_flip,
>> +     .reset = drm_atomic_helper_crtc_reset,
>> +     .atomic_duplicate_state =
>> drm_atomic_helper_crtc_duplicate_state,
>> +     .atomic_destroy_state =
>> drm_atomic_helper_crtc_destroy_state,
>> +};
>> +
>> +static void intelvipfb_crtc_atomic_begin(struct drm_crtc *crtc,
>> +                                      struct drm_crtc_state
>> *state)
>> +{
>> +     struct drm_pending_vblank_event *event = crtc->state->event;
>> +
>> +     if (event) {
>> +             crtc->state->event = NULL;
>> +
>> +             spin_lock_irq(&crtc->dev->event_lock);
>> +             drm_crtc_send_vblank_event(crtc, event);
>> +             spin_unlock_irq(&crtc->dev->event_lock);
>> +     }
>> +}
>> +
>> +static void intelvipfb_crtc_nop(struct drm_crtc *crtc)
>> +{
>> +     /* do nothing */;
>> +}
>> +
>> +static const struct drm_crtc_helper_funcs
>> intelvipfb_crtc_helper_funcs = {
>> +     .atomic_begin   = intelvipfb_crtc_atomic_begin,
>> +     .enable = intelvipfb_crtc_nop,
>> +};
>> +
>> +static void intelvipfb_plane_destroy(struct drm_plane *plane)
>> +{
>> +     drm_plane_helper_disable(plane);
>> +     drm_plane_cleanup(plane);
>> +}
>> +
>> +static const struct drm_plane_funcs intelvipfb_plane_funcs = {
>> +     .update_plane           =
>> drm_atomic_helper_update_plane,
>> +     .disable_plane          =
>> drm_atomic_helper_disable_plane,
>> +     .destroy                = intelvipfb_plane_destroy,
>> +     .reset                  =
>> drm_atomic_helper_plane_reset,
>> +     .atomic_duplicate_state =
>> drm_atomic_helper_plane_duplicate_state,
>> +     .atomic_destroy_state   =
>> drm_atomic_helper_plane_destroy_state,
>> +};
>> +
>> +static void intelvipfb_plane_atomic_update(struct drm_plane *plane,
>> +                                        struct drm_plane_state
>> *state)
>> +{
>> +     struct intelvipfb_priv *fbpriv;
>> +     struct drm_gem_cma_object *gem;
>> +
>> +     if (!plane->state->crtc || !plane->state->fb)
>> +             return;
>> +
>> +     fbpriv = plane->dev->dev_private;
>> +     gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
>> +     writel(gem->paddr, fbpriv->base + INTELVIPFB_FRAME_START);
>> +}
>> +
>> +static const struct drm_plane_helper_funcs
>> intelvipfb_plane_helper_funcs = {
>> +     .atomic_update = intelvipfb_plane_atomic_update,
>> +};
>> +
>> +static struct drm_plane *intelvipfb_plane_init(struct drm_device
>> *drm)
>> +{
>> +     struct drm_plane *plane = NULL;
>> +     u32 formats[ARRAY_SIZE(intelvipfb_formats)], i;
>> +     int ret;
>> +
>> +     plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
>> +     if (!plane)
>> +             return ERR_PTR(-ENOMEM);
>> +
>> +     for (i = 0; i < ARRAY_SIZE(intelvipfb_formats); i++)
>> +             formats[i] = intelvipfb_formats[i].fourcc;
>> +
>> +     ret = drm_universal_plane_init(drm, plane, 0xff,
>> +                                    &intelvipfb_plane_funcs,
>> +                                    formats, ARRAY_SIZE(formats),
>> +                                    DRM_PLANE_TYPE_PRIMARY,
>> NULL);
>> +     if (ret)
>> +             return ERR_PTR(ret);
>> +
>> +     drm_plane_helper_add(plane, &intelvipfb_plane_helper_funcs);
>> +
>> +     return plane;
>> +}
>> +
>> +int intelvipfb_setup_crtc(struct drm_device *drm)
>> +{
>> +     struct drm_crtc *crtc;
>> +     struct drm_plane *primary;
>> +     int ret;
>> +
>> +     crtc = kzalloc(sizeof(*crtc), GFP_KERNEL);
>> +     if (!crtc)
>> +             return -ENOMEM;
>> +
>> +     primary = intelvipfb_plane_init(drm);
>> +     if (IS_ERR(primary))
>> +             return PTR_ERR(primary);
>> +
>> +     ret = drm_crtc_init_with_planes(drm, crtc, primary, NULL,
>> +                                     &intelvipfb_crtc_funcs,
>> NULL);
>> +
>> +     if (ret) {
>> +             intelvipfb_plane_destroy(primary);
>> +             return ret;
>> +     }
>> +
>> +     drm_crtc_helper_add(crtc, &intelvipfb_crtc_helper_funcs);
>> +     return 0;
>> +}
>> diff --git a/drivers/gpu/drm/ivip/intel_vip_drv.h
>> b/drivers/gpu/drm/ivip/intel_vip_drv.h
>> new file mode 100644
>> index 0000000..657f23c
>> --- /dev/null
>> +++ b/drivers/gpu/drm/ivip/intel_vip_drv.h
>> @@ -0,0 +1,55 @@
>> +/*
>> + * Copyright (C) 2017 Intel Corporation.
>> + *
>> + * Intel Video and Image Processing(VIP) Frame Buffer II driver.
>> + *
>> + * 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.
>> + *
>> + * 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.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> along with
>> + * this program.  If not, see <http://www.gnu.org/licenses/>.
>> + *
>> + * Authors:
>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>> + *
>> + */
>> +#ifndef _INTEL_VIP_DRV_H
>> +#define _INTEL_VIP_DRV_H
>> +#include <linux/io.h>
>> +#include <linux/fb.h>
>> +
>> +#define DRIVER_NAME  "intelvipfb"
>> +#define BYTES_PER_PIXEL      4
>> +#define PREF_BPP             32
>> +#define CRTC_NUM             1
>> +#define CONN_NUM             1
>> +
>> +/* control registers */
>> +#define INTELVIPFB_CONTROL           0
>> +#define INTELVIPFB_STATUS            0x4
>> +#define INTELVIPFB_INTERRUPT         0x8
>> +#define INTELVIPFB_FRAME_COUNTER     0xC
>> +#define INTELVIPFB_FRAME_DROP                0x10
>> +#define INTELVIPFB_FRAME_INFO                0x14
>> +#define INTELVIPFB_FRAME_START               0x18
>> +#define INTELVIPFB_FRAME_READER              0x1C
>> +
>> +int intelvipfb_probe(struct device *dev, void __iomem *base);
>> +int intelvipfb_remove(struct device *dev);
>> +int intelvipfb_setup_crtc(struct drm_device *drm);
>> +int intelvipfb_drm_conn_init(struct drm_device *drm);
>> +
>> +struct intelvipfb_priv {
>> +     struct drm_fbdev_cma *fbcma;
>> +     struct drm_device *drm;
>> +     struct fb_info info;
>> +     void    __iomem         *base;
>> +};
>> +
>> +#endif
>> diff --git a/drivers/gpu/drm/ivip/intel_vip_of.c
>> b/drivers/gpu/drm/ivip/intel_vip_of.c
>> new file mode 100644
>> index 0000000..17dff36
>> --- /dev/null
>> +++ b/drivers/gpu/drm/ivip/intel_vip_of.c
>> @@ -0,0 +1,146 @@
>> +/*
>> + * intel_vip_of.c -- Intel Video and Image Processing(VIP)
>> + * Frame Buffer II driver
>> + *
>> + * This driver supports the Intel VIP Frame Reader component.
>> + * More info on the hardware can be found in the Intel Video
>> + * and Image Processing Suite User Guide at this address
>> + * http://www.altera.com/literature/ug/ug_vip.pdf.
>> + *
>> + * 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.
>> + *
>> + * 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.
>> + *
>> + * Authors:
>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>> + *
>> + */
>> +
>> +#include <linux/fb.h>
>> +#include <linux/init.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +
>> +#include <drm/drm_fb_helper.h>
>> +#include "intel_vip_drv.h"
>> +
>> +/*
>> + * Setting up information derived from OF Device Tree Nodes
>> + * max-width, max-height, bits per pixel, memory port width
>> + */
>> +
>> +static int intelvipfb_of_setup(struct intelvipfb_priv *fbdata,
>> +                            struct platform_device *pdev)
>> +{
>> +     int ret;
>> +     int mem_word_width;
>> +     u32 bits_per_color;
>> +     struct device_node *np = pdev->dev.of_node;
>> +
>> +     ret = of_property_read_u32(np, "altr,max-width",
>> +                                &fbdata->info.var.xres);
>> +     if (ret) {
>> +             dev_err(&pdev->dev,
>> +                     "Missing required parameter 'altr,max-
>> width'");
>> +             return ret;
>> +     }
>> +     fbdata->info.var.xres_virtual = fbdata->info.var.xres;
>> +
>> +     ret = of_property_read_u32(np, "altr,max-height",
>> +                                &fbdata->info.var.yres);
>> +     if (ret) {
>> +             dev_err(&pdev->dev,
>> +                     "Missing required parameter 'altr,max-
>> height'");
>> +             return ret;
>> +     }
>> +     fbdata->info.var.yres_virtual = fbdata->info.var.yres;
>> +
>> +     ret = of_property_read_u32(np, "altr,bits-per-symbol",
>> &bits_per_color);
>> +     if (ret) {
>> +             dev_err(&pdev->dev,
>> +                     "Missing required parameter 'altr,bits-per-
>> symbol'");
>> +             return ret;
>> +     }
>> +
>> +     fbdata->info.var.bits_per_pixel = bits_per_color *
>> BYTES_PER_PIXEL;
>> +
>> +     ret = of_property_read_u32(np, "altr,mem-port-width",
>> &mem_word_width);
>> +     if (ret) {
>> +             dev_err(&pdev->dev,
>> +                     "Missing required parameter 'altr,mem-port-
>> width '");
>> +             return ret;
>> +     }
>> +
>> +     if (!(mem_word_width >= 32 && mem_word_width % 32 == 0)) {
>> +             dev_err(&pdev->dev,
>> +                     "mem-word-width is set to %i. must be >= 32
>> and multiple of 32.",
>> +                      mem_word_width);
>> +             return -ENODEV;
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +static int intelvipfb_of_probe(struct platform_device *pdev)
>> +{
>> +     int retval;
>> +     struct resource *reg_res;
>> +     struct intelvipfb_priv *fbdata;
>> +
>> +     fbdata = devm_kzalloc(&pdev->dev, sizeof(*fbdata),
>> GFP_KERNEL);
>> +     if (!fbdata)
>> +             return -ENOMEM;
>> +
>> +     reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +     if (!reg_res)
>> +             return -ENOMEM;
>> +
>> +     fbdata->base = devm_ioremap_resource(&pdev->dev, reg_res);
>> +
>> +     if (IS_ERR(fbdata->base)) {
>> +             dev_err(&pdev->dev, "devm_ioremap_resource
>> failed\n");
>> +             retval = PTR_ERR(fbdata->base);
>> +             return -ENOMEM;
>> +     }
>> +
>> +     intelvipfb_of_setup(fbdata, pdev);
>> +
>> +     platform_set_drvdata(pdev, fbdata);
>> +
>> +     return intelvipfb_probe(&pdev->dev, fbdata->base);
>> +}
>> +
>> +static int intelvipfb_of_remove(struct platform_device *pdev)
>> +{
>> +     return intelvipfb_remove(&pdev->dev);
>> +}
>> +
>> +/*
>> + * The name vip-frame-buffer-2.0 is derived from
>> + * http://www.altera.com/literature/ug/ug_vip.pdf
>> + * frame buffer IP cores section 14
>> + */
>> +
>> +static const struct of_device_id intelvipfb_of_match[] = {
>> +     { .compatible = "altr,vip-frame-buffer-2.0" },
>> +     {},
>> +};
>> +
>> +MODULE_DEVICE_TABLE(of, intelvipfb_of_match);
>> +
>> +static struct platform_driver intelvipfb_driver = {
>> +     .probe = intelvipfb_of_probe,
>> +     .remove = intelvipfb_of_remove,
>> +     .driver = {
>> +             .name = DRIVER_NAME,
>> +             .of_match_table = intelvipfb_of_match,
>> +     },
>> +};
>> +
>> +module_platform_driver(intelvipfb_driver);
>> --
>> 1.7.1
>>
>>
>> -----Original Message-----
>> From: Ong, Hean Loong
>> Sent: Friday, March 31, 2017 5:09 PM
>> To: Vetter, Daniel <daniel.vetter@intel.com>; airlied@linux.ie
>> Cc: dri-devel@lists.freedesktop.org
>> Subject: DRM Display driver for Intel FPGA Video and Image Processing
>> Suite
>>
>> Hi,
>>
>> I would like to upstream the attached Intel FPGA Video and Image
>> Processing Suite. The attached patch supports the Intel Arria10
>> devkit and its variants. The purpose of the patch is to enable the
>> FPGA driven display designed from the Intel Quartus FPGA design
>> suite.
>>
>> The driver is required as part of the Intel Arria10 devkit reference
>> design. The driver was tested on:
>> - The Open Embedded Angstrom Distro.
>> - The matchbox-terminal and window-manager was used for functional
>> testing
>>
>> Current the intention of the driver is meant to validate the FPGA
>> designs on the Arria10 devkit for Display Port connecter. We have not
>> verified its performance of or stability in 3D acceleration or other
>> non Intel FPGA hardware
>>
>> BR
>>
>> Hean Loong
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel



-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: DRM Display driver for Intel FPGA Video and Image Processing Suite
  2017-04-07 16:31     ` Daniel Vetter
@ 2017-04-08  5:41       ` Ong, Hean Loong
  2017-04-08 16:31         ` Daniel Vetter
  0 siblings, 1 reply; 9+ messages in thread
From: Ong, Hean Loong @ 2017-04-08  5:41 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Vetter, Daniel, Ong, Hean Loong, dri-devel

Hi Daniel

Thanks for the time and patience for reviewing my changes. I would ensure that subsequent patches will not have the same mail problems.

I have some question on the validation methods. Since my drivers are processing the images with an FPGA would running the tests with https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#testing-and-validation be relevant? 

The display images are streamed to the monitor via a Display Port connector thus I don' t think it is virtual. The FPGA is programmed to run with a proprietary Display Port IP. The driver just feeds it with display data.

I would take your advice in implementing it in the small drivers, but since its new are there any special cases that I would have to look out for in implementing this driver in the drm-misc ?

>-----Original Message-----
>From: daniel.vetter@ffwll.ch [mailto:daniel.vetter@ffwll.ch] On Behalf Of Daniel
>Vetter
>Sent: Saturday, April 8, 2017 12:32 AM
>To: Ong, Hean Loong <hean.loong.ong@intel.com>
>Cc: Vetter, Daniel <daniel.vetter@intel.com>; airlied@linux.ie; dri-
>devel@lists.freedesktop.org
>Subject: Re: DRM Display driver for Intel FPGA Video and Image Processing Suite
>
>On Thu, Apr 6, 2017 at 8:29 AM, Ong, Hean Loong <hean.loong.ong@intel.com>
>wrote:
>> Hi All,
>>
>> Any comments for the patch below?
>
>Seems the same version that I already reviewed. My comment about not sending
>inline was more for the next version, especially once it's about applying the
>patch, attached patches are a bit of a pain (since they break the tooling here).
>-Daniel
>>
>> Thanks
>>
>> Hean Loong
>>
>> On Tue, 2017-04-04 at 04:01 +0000, Ong, Hean Loong wrote:
>>> Hi All,
>>>
>>> Apologies for the attachment earlier. Below are the inline changes
>>> for the patch
>>>
>>> From 0de293e3646a1780ed603cf8e1f2a19d9aebbe83 Mon Sep 17 00:00:00
>>> 2001
>>> From: Ong, Hean Loong <hean.loong.ong@intel.com>
>>> Date: Thu, 30 Mar 2017 18:02:22 +0800
>>> Subject: [PATCHv0] Intel FPGA Video and Image Processing Suite Frame
>>> Buffer II driver
>>>
>>> Signed-off-by: Ong, Hean Loong <hean.loong.ong@intel.com>
>>> ---
>>>  drivers/gpu/drm/Kconfig               |    2 +
>>>  drivers/gpu/drm/Makefile              |    1 +
>>>  drivers/gpu/drm/ivip/Kconfig          |   22 ++++
>>>  drivers/gpu/drm/ivip/Makefile         |    9 ++
>>>  drivers/gpu/drm/ivip/intel_vip_conn.c |  145 ++++++++++++++++++++++
>>> drivers/gpu/drm/ivip/intel_vip_core.c |  215
>>> +++++++++++++++++++++++++++++++++
>>>  drivers/gpu/drm/ivip/intel_vip_crtc.c |  161
>>> ++++++++++++++++++++++++
>>>  drivers/gpu/drm/ivip/intel_vip_drv.h  |   55 +++++++++
>>>  drivers/gpu/drm/ivip/intel_vip_of.c   |  146 ++++++++++++++++++++++
>>>  9 files changed, 756 insertions(+), 0 deletions(-)  create mode
>>> 100644 drivers/gpu/drm/ivip/Kconfig  create mode 100644
>>> drivers/gpu/drm/ivip/Makefile  create mode 100644
>>> drivers/gpu/drm/ivip/intel_vip_conn.c
>>>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_core.c
>>>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_crtc.c
>>>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_drv.h
>>>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_of.c
>>>
>>> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index
>>> ebfe840..c487507 100644
>>> --- a/drivers/gpu/drm/Kconfig
>>> +++ b/drivers/gpu/drm/Kconfig
>>> @@ -167,6 +167,8 @@ source "drivers/gpu/drm/nouveau/Kconfig"
>>>
>>>  source "drivers/gpu/drm/i915/Kconfig"
>>>
>>> +source "drivers/gpu/drm/ivip/Kconfig"
>>> +
>>>  config DRM_VGEM
>>>       tristate "Virtual GEM provider"
>>>       depends on DRM
>>> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
>>> index b9ae428..945cf53 100644
>>> --- a/drivers/gpu/drm/Makefile
>>> +++ b/drivers/gpu/drm/Makefile
>>> @@ -52,6 +52,7 @@ obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/
>>>  obj-$(CONFIG_DRM_MGA)        += mga/
>>>  obj-$(CONFIG_DRM_I810)       += i810/
>>>  obj-$(CONFIG_DRM_I915)       += i915/
>>> +obj-$(CONFIG_DRM_IVIP)       += ivip/
>>>  obj-$(CONFIG_DRM_MGAG200) += mgag200/
>>>  obj-$(CONFIG_DRM_VC4)  += vc4/
>>>  obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus/ diff --git
>>> a/drivers/gpu/drm/ivip/Kconfig b/drivers/gpu/drm/ivip/Kconfig new
>>> file mode 100644 index 0000000..ddf3cb5
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/ivip/Kconfig
>>> @@ -0,0 +1,22 @@
>>> +config DRM_IVIP
>>> +        tristate "Intel FGPA Video and Image Processing"
>>> +        depends on DRM
>>> +        select DRM_GEM_CMA_HELPER
>>> +        select DRM_KMS_HELPER
>>> +        select DRM_KMS_FB_HELPER
>>> +        select DRM_KMS_CMA_HELPER
>>> +        help
>>> +                Choose this option if you have a Intel FPGA Arria 10
>>> system
>>> +                and above with a Display Port IP. This does not
>>> support legacy
>>> +                Intel FPGA Cyclone V display port. Currently only
>>> single frame
>>> +                buffer is supported. Note that ACPI and X_86
>>> architecture is yet
>>> +                to be supported.
>>> +
>>> +config DRM_IVIP_OF
>>> +        tristate "Intel FGPA Video and Image Processing Open
>>> Firmware Systems"
>>> +        depends on DRM_IVIP && OF
>>> +        help
>>> +                Choose this option if the Intel FPGA system is using
>>> Open
>>> +                Firmware systems (Arria 10). If M is selected the
>>> module would
>>> +                be called ivip.
>>> +
>>> diff --git a/drivers/gpu/drm/ivip/Makefile
>>> b/drivers/gpu/drm/ivip/Makefile new file mode 100644 index
>>> 0000000..7be1e99
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/ivip/Makefile
>>> @@ -0,0 +1,9 @@
>>> +#
>>> +# Makefile for the drm device driver.  This driver provides support
>>> for the
>>> +# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
>>> +
>>> +ccflags-y := -Iinclude/drm
>>> +
>>> +obj-$(CONFIG_DRM_IVIP_OF) += ivip.o
>>> +ivip-objs := intel_vip_of.o intel_vip_core.o \ intel_vip_conn.o
>>> +intel_vip_crtc.o
>>> diff --git a/drivers/gpu/drm/ivip/intel_vip_conn.c
>>> b/drivers/gpu/drm/ivip/intel_vip_conn.c
>>> new file mode 100644
>>> index 0000000..89ab587
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/ivip/intel_vip_conn.c
>>> @@ -0,0 +1,145 @@
>>> +/*
>>> + * intel_vip_conn.c -- Intel Video and Image Processing(VIP)
>>> + * Frame Buffer II driver
>>> + *
>>> + * This driver supports the Intel VIP Frame Reader component.
>>> + * More info on the hardware can be found in the Intel Video
>>> + * and Image Processing Suite User Guide at this address
>>> + * http://www.altera.com/literature/ug/ug_vip.pdf.
>>> + *
>>> + * 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.
>>> + *
>>> + * 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.
>>> + *
>>> + * Authors:
>>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>>> + *
>>> + */
>>> +
>>> +#include <linux/init.h>
>>> +#include <linux/kernel.h>
>>> +#include <drm/drm_atomic_helper.h>
>>> +#include <drm/drm_crtc_helper.h>
>>> +#include <drm/drm_encoder_slave.h>
>>> +#include <drm/drm_plane_helper.h>
>>> +
>>> +static enum drm_connector_status
>>> +intelvipfb_drm_connector_detect(struct drm_connector *connector,
>>> bool force)
>>> +{
>>> +     return connector_status_connected; }
>>> +
>>> +static void intelvipfb_drm_connector_destroy(struct drm_connector
>>> *connector)
>>> +{
>>> +     drm_connector_unregister(connector);
>>> +     drm_connector_cleanup(connector); }
>>> +
>>> +static const struct drm_connector_funcs
>>> intelvipfb_drm_connector_funcs = {
>>> +     .dpms = drm_helper_connector_dpms,
>>> +     .reset = drm_atomic_helper_connector_reset,
>>> +     .detect = intelvipfb_drm_connector_detect,
>>> +     .fill_modes = drm_helper_probe_single_connector_modes,
>>> +     .destroy = intelvipfb_drm_connector_destroy,
>>> +     .atomic_duplicate_state =
>>> drm_atomic_helper_connector_duplicate_state,
>>> +     .atomic_destroy_state =
>>> drm_atomic_helper_connector_destroy_state,
>>> +};
>>> +
>>> +static int intelvipfb_drm_connector_get_modes(struct drm_connector
>>> *connector)
>>> +{
>>> +     struct drm_device *drm = connector->dev;
>>> +     int count;
>>> +
>>> +     count = drm_add_modes_noedid(connector, drm-
>>> >mode_config.max_width,
>>> +                                  drm->mode_config.max_height);
>>> +     drm_set_preferred_mode(connector, drm-
>>> >mode_config.max_width,
>>> +                            drm->mode_config.max_height);
>>> +     return count;
>>> +}
>>> +
>>> +static const struct drm_connector_helper_funcs
>>> +intelvipfb_drm_connector_helper_funcs = {
>>> +     .get_modes = intelvipfb_drm_connector_get_modes,
>>> +};
>>> +
>>> +static const struct drm_encoder_funcs intelvipfb_drm_encoder_funcs =
>>> +{
>>> +     .destroy = drm_encoder_cleanup, };
>>> +
>>> +static void intelvipfb_mode_set(struct drm_encoder *encoder,
>>> +                             struct drm_display_mode *mode,
>>> +                             struct drm_display_mode
>>> *adjusted_mode)
>>> +{
>>> +     /* do nothing */
>>> +}
>>> +
>>> +static void intelvipfb_nop(struct drm_encoder *encoder) {
>>> +     /* do nothing */
>>> +}
>>> +
>>> +static const struct drm_encoder_helper_funcs i
>>> +intelvipfb_drm_encoder_helper = {
>>> +     .mode_set = intelvipfb_mode_set,
>>> +     .enable = intelvipfb_nop,
>>> +     .disable = intelvipfb_nop,
>>> +};
>>> +
>>> +int intelvipfb_drm_conn_init(struct drm_device *drm) {
>>> +     struct drm_encoder_slave *encoder;
>>> +     struct drm_connector *conn;
>>> +     int ret;
>>> +
>>> +     encoder = devm_kzalloc(drm->dev, sizeof(*encoder),
>>> GFP_KERNEL);
>>> +     if (!encoder)
>>> +             return -ENOMEM;
>>> +
>>> +     encoder->base.possible_crtcs = 1;
>>> +     encoder->base.possible_clones = 0;
>>> +
>>> +     ret = drm_encoder_init(drm, &encoder->base,
>>> +                            &intelvipfb_drm_encoder_funcs,
>>> +                            DRM_MODE_ENCODER_VIRTUAL, NULL);
>>> +     if (ret)
>>> +             return ret;
>>> +
>>> +     drm_encoder_helper_add(&encoder->base,
>>> &intelvipfb_drm_encoder_helper);
>>> +
>>> +     conn = devm_kzalloc(drm->dev, sizeof(*conn), GFP_KERNEL);
>>> +     if (IS_ERR(conn))
>>> +             return PTR_ERR(conn);
>>> +
>>> +     ret = drm_connector_init(drm, conn,
>>> &intelvipfb_drm_connector_funcs,
>>> +                              DRM_MODE_CONNECTOR_DisplayPort);
>>> +     if (ret < 0) {
>>> +             dev_err(drm->dev, "failed to initialize drm
>>> connector\n");
>>> +             ret = -ENOMEM;
>>> +             goto error_encoder_cleanup;
>>> +     }
>>> +
>>> +     drm_connector_helper_add(conn,
>>> &intelvipfb_drm_connector_helper_funcs);
>>> +
>>> +     ret = drm_mode_connector_attach_encoder(conn, &encoder-
>>> >base);
>>> +     if (ret < 0) {
>>> +             dev_err(drm->dev, "could not attach connector to
>>> encoder\n");
>>> +             drm_connector_unregister(conn);
>>> +             goto error_connector_cleanup;
>>> +     }
>>> +
>>> +     return 0;
>>> +
>>> +error_connector_cleanup:
>>> +     drm_connector_cleanup(conn);
>>> +
>>> +error_encoder_cleanup:
>>> +     drm_encoder_cleanup(&encoder->base);
>>> +
>>> +     return ret;
>>> +}
>>> diff --git a/drivers/gpu/drm/ivip/intel_vip_core.c
>>> b/drivers/gpu/drm/ivip/intel_vip_core.c
>>> new file mode 100644
>>> index 0000000..3001ad0
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/ivip/intel_vip_core.c
>>> @@ -0,0 +1,215 @@
>>> +/*
>>> + * intel_vip_core.c -- Intel Video and Image Processing(VIP)
>>> + * Frame Buffer II driver
>>> + *
>>> + * This driver supports the Intel VIP Frame Reader component.
>>> + * More info on the hardware can be found in the Intel Video
>>> + * and Image Processing Suite User Guide at this address
>>> + * http://www.altera.com/literature/ug/ug_vip.pdf.
>>> + *
>>> + * 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.
>>> + *
>>> + * 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.
>>> + *
>>> + * Authors:
>>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>>> + *
>>> + */
>>> +
>>> +#include <linux/init.h>
>>> +#include <linux/kernel.h>
>>> +#include <linux/module.h>
>>> +
>>> +#include <drm/drmP.h>
>>> +#include <drm/drm_atomic.h>
>>> +#include <drm/drm_atomic_helper.h>
>>> +#include <drm/drm_crtc_helper.h>
>>> +#include <drm/drm_fb_helper.h>
>>> +#include <drm/drm_fb_cma_helper.h>
>>> +#include <drm/drm_gem_cma_helper.h>
>>> +#include <drm/drm_of.h>
>>> +
>>> +#include "intel_vip_drv.h"
>>> +
>>> +static const struct file_operations intelvipfb_drm_fops = {
>>> +     .owner          = THIS_MODULE,
>>> +     .open           = drm_open,
>>> +     .release        = drm_release,
>>> +     .unlocked_ioctl = drm_ioctl,
>>> +     .poll           = drm_poll,
>>> +     .read           = drm_read,
>>> +     .llseek         = no_llseek,
>>> +     .mmap           = drm_gem_cma_mmap,
>>> +};
>>> +
>>> +static void intelvipfb_lastclose(struct drm_device *drm) {
>>> +     struct intelvipfb_priv *fbpriv = drm->dev_private;
>>> +
>>> +     drm_fbdev_cma_restore_mode(fbpriv->fbcma);
>>> +}
>>> +
>>> +static struct drm_driver intelvipfb_drm = {
>>> +     .driver_features =
>>> +         DRIVER_GEM | DRIVER_PRIME |
>>> +         DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC,
>>> +     .gem_free_object_unlocked = drm_gem_cma_free_object,
>>> +     .gem_vm_ops = &drm_gem_cma_vm_ops,
>>> +     .dumb_create = drm_gem_cma_dumb_create,
>>> +     .dumb_map_offset = drm_gem_cma_dumb_map_offset,
>>> +     .dumb_destroy = drm_gem_dumb_destroy,
>>> +     .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
>>> +     .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
>>> +     .gem_prime_export = drm_gem_prime_export,
>>> +     .gem_prime_import = drm_gem_prime_import,
>>> +     .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
>>> +     .gem_prime_import_sg_table =
>>> drm_gem_cma_prime_import_sg_table,
>>> +     .gem_prime_vmap = drm_gem_cma_prime_vmap,
>>> +     .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
>>> +     .gem_prime_mmap = drm_gem_cma_prime_mmap,
>>> +     .name = DRIVER_NAME,
>>> +     .date = "20170329",
>>> +     .desc = "Intel FPGA VIP SUITE",
>>> +     .major = 1,
>>> +     .minor = 0,
>>> +     .patchlevel = 0,
>>> +     .lastclose = intelvipfb_lastclose,
>>> +     .fops = &intelvipfb_drm_fops,
>>> +};
>>> +
>>> +static void intelvipfb_start_hw(void __iomem *base, resource_size_t
>>> addr)
>>> +{
>>> +     /*
>>> +      * The frameinfo variable has to correspond to the size of
>>> the VIP Suite
>>> +      * Frame Reader register 7 which will determine the maximum
>>> size used
>>> +      * in this frameinfo
>>> +      */
>>> +
>>> +     u32 frameinfo;
>>> +
>>> +     frameinfo =
>>> +             readl(base + INTELVIPFB_FRAME_READER) & 0x00ffffff;
>>> +
>>> +     writel(frameinfo, base + INTELVIPFB_FRAME_INFO);
>>> +
>>> +     writel(addr, base + INTELVIPFB_FRAME_START);
>>> +     /* Finally set the control register to 1 to start streaming
>>> */
>>> +     writel(1, base + INTELVIPFB_CONTROL); }
>>> +
>>> +static void intelvipfb_disable_hw(void __iomem *base) {
>>> +     /* set the control register to 0 to stop streaming */
>>> +     writel(0, base + INTELVIPFB_CONTROL); }
>>> +
>>> +static void intelvipfb_output_poll_changed(struct drm_device *drm) {
>>> +     struct intelvipfb_priv *fbpriv = drm->dev_private;
>>> +
>>> +     drm_fbdev_cma_hotplug_event(fbpriv->fbcma);
>>> +}
>>> +
>>> +static const struct drm_mode_config_funcs
>>> intelvipfb_mode_config_funcs = {
>>> +     .fb_create = drm_fb_cma_create,
>>> +     .output_poll_changed = intelvipfb_output_poll_changed,
>>> +     .atomic_check = drm_atomic_helper_check,
>>> +     .atomic_commit = drm_atomic_helper_commit, };
>>> +
>>> +static struct drm_mode_config_helper_funcs
>>> intelvipfb_mode_config_helpers = {
>>> +     .atomic_commit_tail = drm_atomic_helper_commit_tail, };
>>> +
>>> +static void intelvipfb_setup_mode_config(struct drm_device *drm,
>>> +                                      struct fb_info *info) {
>>> +     drm_mode_config_init(drm);
>>> +     drm->mode_config.min_width = 0;
>>> +     drm->mode_config.min_height = 0;
>>> +     drm->mode_config.max_width = info->var.xres;
>>> +     drm->mode_config.max_height = info->var.yres;
>>> +     drm->mode_config.preferred_depth = 32;
>>> +     drm->mode_config.funcs = &intelvipfb_mode_config_funcs;
>>> +     drm->mode_config.helper_private =
>>> &intelvipfb_mode_config_helpers;
>>> +}
>>> +
>>> +int intelvipfb_probe(struct device *dev, void __iomem *base) {
>>> +     int retval;
>>> +     struct drm_device *drm;
>>> +     struct intelvipfb_priv *fbpriv = dev_get_drvdata(dev);
>>> +     struct fb_info *info = &fbpriv->info;
>>> +
>>> +     /*setup DRM */
>>> +     drm = drm_dev_alloc(&intelvipfb_drm, dev);
>>> +     if (IS_ERR(drm))
>>> +             return PTR_ERR(drm);
>>> +
>>> +     drm->dev_private = fbpriv;
>>> +
>>> +     dev_set_drvdata(dev, drm);
>>> +
>>> +     intelvipfb_setup_mode_config(drm, info);
>>> +
>>> +     retval = dma_set_mask_and_coherent(drm->dev,
>>> DMA_BIT_MASK(32));
>>> +     if (retval)
>>> +             return -ENODEV;
>>> +
>>> +     retval = intelvipfb_setup_crtc(drm);
>>> +     if (retval < 0)
>>> +             return -ENODEV;
>>> +
>>> +     retval = intelvipfb_drm_conn_init(drm);
>>> +     if (retval)
>>> +             return -ENOMEM;
>>> +
>>> +     drm_mode_config_reset(drm);
>>> +
>>> +     fbpriv->fbcma = drm_fbdev_cma_init(drm, PREF_BPP,
>>> +                                                     CRTC_NUM,
>>> CONN_NUM);
>>> +     if (!fbpriv->fbcma) {
>>> +             fbpriv->fbcma = NULL;
>>> +             return -ENODEV;
>>> +     }
>>> +
>>> +     intelvipfb_start_hw(base, drm->mode_config.fb_base);
>>> +
>>> +     drm_kms_helper_poll_init(drm);
>>> +
>>> +     drm_dev_register(drm, 0);
>>> +
>>> +     return retval;
>>> +}
>>> +EXPORT_SYMBOL_GPL(intelvipfb_probe);
>>> +
>>> +int intelvipfb_remove(struct device *dev) {
>>> +     struct drm_device *drm = dev_get_drvdata(dev);
>>> +     struct intelvipfb_priv *fbpriv = drm->dev_private;
>>> +
>>> +     drm_dev_unregister(drm);
>>> +
>>> +     drm_kms_helper_poll_fini(drm);
>>> +     drm_fbdev_cma_fini(fbpriv->fbcma);
>>> +
>>> +     intelvipfb_disable_hw(fbpriv->base);
>>> +
>>> +drm_mode_config_cleanup(drm);
>>> +
>>> +drm_dev_unref(drm);
>>> +
>>> +devm_kfree(dev, fbpriv);
>>> +
>>> +     return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(intelvipfb_remove);
>>> +
>>> +MODULE_AUTHOR("Ong, Hean-Loong <hean.loong.ong@intel.com>");
>>> +MODULE_DESCRIPTION("Intel VIP Frame Buffer II driver");
>>> +MODULE_LICENSE("GPL v2");
>>> diff --git a/drivers/gpu/drm/ivip/intel_vip_crtc.c
>>> b/drivers/gpu/drm/ivip/intel_vip_crtc.c
>>> new file mode 100644
>>> index 0000000..97a3954
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/ivip/intel_vip_crtc.c
>>> @@ -0,0 +1,161 @@
>>> +/*
>>> + * intel_vip_crtc.c -- Intel Video and Image Processing(VIP)
>>> + * Frame Buffer II driver
>>> + *
>>> + * This driver supports the Intel VIP Frame Reader component.
>>> + * More info on the hardware can be found in the Intel Video
>>> + * and Image Processing Suite User Guide at this address
>>> + * http://www.altera.com/literature/ug/ug_vip.pdf.
>>> + *
>>> + * 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.
>>> + *
>>> + * 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.
>>> + *
>>> + * Authors:
>>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>>> + *
>>> + */
>>> +
>>> +#include <linux/init.h>
>>> +#include <linux/kernel.h>
>>> +#include <linux/platform_data/simplefb.h>
>>> +
>>> +#include <drm/drm_atomic.h>
>>> +#include <drm/drm_atomic_helper.h>
>>> +#include <drm/drm_crtc.h>
>>> +#include <drm/drm_crtc_helper.h>
>>> +#include <drm/drm_fb_cma_helper.h>
>>> +#include <drm/drm_gem_cma_helper.h>
>>> +#include <drm/drm_plane_helper.h>
>>> +
>>> +#include "intel_vip_drv.h"
>>> +
>>> +static struct simplefb_format intelvipfb_formats[] =
>>> SIMPLEFB_FORMATS;
>>> +
>>> +static void intelvipfb_crtc_destroy(struct drm_crtc *crtc) {
>>> +     drm_crtc_cleanup(crtc);
>>> +     kfree(crtc);
>>> +}
>>> +
>>> +static const struct drm_crtc_funcs intelvipfb_crtc_funcs = {
>>> +     .destroy = intelvipfb_crtc_destroy,
>>> +     .set_config = drm_atomic_helper_set_config,
>>> +     .page_flip = drm_atomic_helper_page_flip,
>>> +     .reset = drm_atomic_helper_crtc_reset,
>>> +     .atomic_duplicate_state =
>>> drm_atomic_helper_crtc_duplicate_state,
>>> +     .atomic_destroy_state =
>>> drm_atomic_helper_crtc_destroy_state,
>>> +};
>>> +
>>> +static void intelvipfb_crtc_atomic_begin(struct drm_crtc *crtc,
>>> +                                      struct drm_crtc_state
>>> *state)
>>> +{
>>> +     struct drm_pending_vblank_event *event = crtc->state->event;
>>> +
>>> +     if (event) {
>>> +             crtc->state->event = NULL;
>>> +
>>> +             spin_lock_irq(&crtc->dev->event_lock);
>>> +             drm_crtc_send_vblank_event(crtc, event);
>>> +             spin_unlock_irq(&crtc->dev->event_lock);
>>> +     }
>>> +}
>>> +
>>> +static void intelvipfb_crtc_nop(struct drm_crtc *crtc) {
>>> +     /* do nothing */;
>>> +}
>>> +
>>> +static const struct drm_crtc_helper_funcs
>>> intelvipfb_crtc_helper_funcs = {
>>> +     .atomic_begin   = intelvipfb_crtc_atomic_begin,
>>> +     .enable = intelvipfb_crtc_nop,
>>> +};
>>> +
>>> +static void intelvipfb_plane_destroy(struct drm_plane *plane) {
>>> +     drm_plane_helper_disable(plane);
>>> +     drm_plane_cleanup(plane);
>>> +}
>>> +
>>> +static const struct drm_plane_funcs intelvipfb_plane_funcs = {
>>> +     .update_plane           =
>>> drm_atomic_helper_update_plane,
>>> +     .disable_plane          =
>>> drm_atomic_helper_disable_plane,
>>> +     .destroy                = intelvipfb_plane_destroy,
>>> +     .reset                  =
>>> drm_atomic_helper_plane_reset,
>>> +     .atomic_duplicate_state =
>>> drm_atomic_helper_plane_duplicate_state,
>>> +     .atomic_destroy_state   =
>>> drm_atomic_helper_plane_destroy_state,
>>> +};
>>> +
>>> +static void intelvipfb_plane_atomic_update(struct drm_plane *plane,
>>> +                                        struct drm_plane_state
>>> *state)
>>> +{
>>> +     struct intelvipfb_priv *fbpriv;
>>> +     struct drm_gem_cma_object *gem;
>>> +
>>> +     if (!plane->state->crtc || !plane->state->fb)
>>> +             return;
>>> +
>>> +     fbpriv = plane->dev->dev_private;
>>> +     gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
>>> +     writel(gem->paddr, fbpriv->base + INTELVIPFB_FRAME_START); }
>>> +
>>> +static const struct drm_plane_helper_funcs
>>> intelvipfb_plane_helper_funcs = {
>>> +     .atomic_update = intelvipfb_plane_atomic_update, };
>>> +
>>> +static struct drm_plane *intelvipfb_plane_init(struct drm_device
>>> *drm)
>>> +{
>>> +     struct drm_plane *plane = NULL;
>>> +     u32 formats[ARRAY_SIZE(intelvipfb_formats)], i;
>>> +     int ret;
>>> +
>>> +     plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
>>> +     if (!plane)
>>> +             return ERR_PTR(-ENOMEM);
>>> +
>>> +     for (i = 0; i < ARRAY_SIZE(intelvipfb_formats); i++)
>>> +             formats[i] = intelvipfb_formats[i].fourcc;
>>> +
>>> +     ret = drm_universal_plane_init(drm, plane, 0xff,
>>> +                                    &intelvipfb_plane_funcs,
>>> +                                    formats, ARRAY_SIZE(formats),
>>> +                                    DRM_PLANE_TYPE_PRIMARY,
>>> NULL);
>>> +     if (ret)
>>> +             return ERR_PTR(ret);
>>> +
>>> +     drm_plane_helper_add(plane, &intelvipfb_plane_helper_funcs);
>>> +
>>> +     return plane;
>>> +}
>>> +
>>> +int intelvipfb_setup_crtc(struct drm_device *drm) {
>>> +     struct drm_crtc *crtc;
>>> +     struct drm_plane *primary;
>>> +     int ret;
>>> +
>>> +     crtc = kzalloc(sizeof(*crtc), GFP_KERNEL);
>>> +     if (!crtc)
>>> +             return -ENOMEM;
>>> +
>>> +     primary = intelvipfb_plane_init(drm);
>>> +     if (IS_ERR(primary))
>>> +             return PTR_ERR(primary);
>>> +
>>> +     ret = drm_crtc_init_with_planes(drm, crtc, primary, NULL,
>>> +                                     &intelvipfb_crtc_funcs,
>>> NULL);
>>> +
>>> +     if (ret) {
>>> +             intelvipfb_plane_destroy(primary);
>>> +             return ret;
>>> +     }
>>> +
>>> +     drm_crtc_helper_add(crtc, &intelvipfb_crtc_helper_funcs);
>>> +     return 0;
>>> +}
>>> diff --git a/drivers/gpu/drm/ivip/intel_vip_drv.h
>>> b/drivers/gpu/drm/ivip/intel_vip_drv.h
>>> new file mode 100644
>>> index 0000000..657f23c
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/ivip/intel_vip_drv.h
>>> @@ -0,0 +1,55 @@
>>> +/*
>>> + * Copyright (C) 2017 Intel Corporation.
>>> + *
>>> + * Intel Video and Image Processing(VIP) Frame Buffer II driver.
>>> + *
>>> + * 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.
>>> + *
>>> + * 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.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> along with
>>> + * this program.  If not, see <http://www.gnu.org/licenses/>.
>>> + *
>>> + * Authors:
>>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>>> + *
>>> + */
>>> +#ifndef _INTEL_VIP_DRV_H
>>> +#define _INTEL_VIP_DRV_H
>>> +#include <linux/io.h>
>>> +#include <linux/fb.h>
>>> +
>>> +#define DRIVER_NAME  "intelvipfb"
>>> +#define BYTES_PER_PIXEL      4
>>> +#define PREF_BPP             32
>>> +#define CRTC_NUM             1
>>> +#define CONN_NUM             1
>>> +
>>> +/* control registers */
>>> +#define INTELVIPFB_CONTROL           0
>>> +#define INTELVIPFB_STATUS            0x4
>>> +#define INTELVIPFB_INTERRUPT         0x8
>>> +#define INTELVIPFB_FRAME_COUNTER     0xC
>>> +#define INTELVIPFB_FRAME_DROP                0x10
>>> +#define INTELVIPFB_FRAME_INFO                0x14
>>> +#define INTELVIPFB_FRAME_START               0x18
>>> +#define INTELVIPFB_FRAME_READER              0x1C
>>> +
>>> +int intelvipfb_probe(struct device *dev, void __iomem *base); int
>>> +intelvipfb_remove(struct device *dev); int
>>> +intelvipfb_setup_crtc(struct drm_device *drm); int
>>> +intelvipfb_drm_conn_init(struct drm_device *drm);
>>> +
>>> +struct intelvipfb_priv {
>>> +     struct drm_fbdev_cma *fbcma;
>>> +     struct drm_device *drm;
>>> +     struct fb_info info;
>>> +     void    __iomem         *base;
>>> +};
>>> +
>>> +#endif
>>> diff --git a/drivers/gpu/drm/ivip/intel_vip_of.c
>>> b/drivers/gpu/drm/ivip/intel_vip_of.c
>>> new file mode 100644
>>> index 0000000..17dff36
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/ivip/intel_vip_of.c
>>> @@ -0,0 +1,146 @@
>>> +/*
>>> + * intel_vip_of.c -- Intel Video and Image Processing(VIP)
>>> + * Frame Buffer II driver
>>> + *
>>> + * This driver supports the Intel VIP Frame Reader component.
>>> + * More info on the hardware can be found in the Intel Video
>>> + * and Image Processing Suite User Guide at this address
>>> + * http://www.altera.com/literature/ug/ug_vip.pdf.
>>> + *
>>> + * 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.
>>> + *
>>> + * 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.
>>> + *
>>> + * Authors:
>>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>>> + *
>>> + */
>>> +
>>> +#include <linux/fb.h>
>>> +#include <linux/init.h>
>>> +#include <linux/kernel.h>
>>> +#include <linux/module.h>
>>> +#include <linux/platform_device.h>
>>> +
>>> +#include <drm/drm_fb_helper.h>
>>> +#include "intel_vip_drv.h"
>>> +
>>> +/*
>>> + * Setting up information derived from OF Device Tree Nodes
>>> + * max-width, max-height, bits per pixel, memory port width  */
>>> +
>>> +static int intelvipfb_of_setup(struct intelvipfb_priv *fbdata,
>>> +                            struct platform_device *pdev) {
>>> +     int ret;
>>> +     int mem_word_width;
>>> +     u32 bits_per_color;
>>> +     struct device_node *np = pdev->dev.of_node;
>>> +
>>> +     ret = of_property_read_u32(np, "altr,max-width",
>>> +                                &fbdata->info.var.xres);
>>> +     if (ret) {
>>> +             dev_err(&pdev->dev,
>>> +                     "Missing required parameter 'altr,max-
>>> width'");
>>> +             return ret;
>>> +     }
>>> +     fbdata->info.var.xres_virtual = fbdata->info.var.xres;
>>> +
>>> +     ret = of_property_read_u32(np, "altr,max-height",
>>> +                                &fbdata->info.var.yres);
>>> +     if (ret) {
>>> +             dev_err(&pdev->dev,
>>> +                     "Missing required parameter 'altr,max-
>>> height'");
>>> +             return ret;
>>> +     }
>>> +     fbdata->info.var.yres_virtual = fbdata->info.var.yres;
>>> +
>>> +     ret = of_property_read_u32(np, "altr,bits-per-symbol",
>>> &bits_per_color);
>>> +     if (ret) {
>>> +             dev_err(&pdev->dev,
>>> +                     "Missing required parameter 'altr,bits-per-
>>> symbol'");
>>> +             return ret;
>>> +     }
>>> +
>>> +     fbdata->info.var.bits_per_pixel = bits_per_color *
>>> BYTES_PER_PIXEL;
>>> +
>>> +     ret = of_property_read_u32(np, "altr,mem-port-width",
>>> &mem_word_width);
>>> +     if (ret) {
>>> +             dev_err(&pdev->dev,
>>> +                     "Missing required parameter 'altr,mem-port-
>>> width '");
>>> +             return ret;
>>> +     }
>>> +
>>> +     if (!(mem_word_width >= 32 && mem_word_width % 32 == 0)) {
>>> +             dev_err(&pdev->dev,
>>> +                     "mem-word-width is set to %i. must be >= 32
>>> and multiple of 32.",
>>> +                      mem_word_width);
>>> +             return -ENODEV;
>>> +     }
>>> +
>>> +     return 0;
>>> +}
>>> +
>>> +static int intelvipfb_of_probe(struct platform_device *pdev) {
>>> +     int retval;
>>> +     struct resource *reg_res;
>>> +     struct intelvipfb_priv *fbdata;
>>> +
>>> +     fbdata = devm_kzalloc(&pdev->dev, sizeof(*fbdata),
>>> GFP_KERNEL);
>>> +     if (!fbdata)
>>> +             return -ENOMEM;
>>> +
>>> +     reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> +     if (!reg_res)
>>> +             return -ENOMEM;
>>> +
>>> +     fbdata->base = devm_ioremap_resource(&pdev->dev, reg_res);
>>> +
>>> +     if (IS_ERR(fbdata->base)) {
>>> +             dev_err(&pdev->dev, "devm_ioremap_resource
>>> failed\n");
>>> +             retval = PTR_ERR(fbdata->base);
>>> +             return -ENOMEM;
>>> +     }
>>> +
>>> +     intelvipfb_of_setup(fbdata, pdev);
>>> +
>>> +     platform_set_drvdata(pdev, fbdata);
>>> +
>>> +     return intelvipfb_probe(&pdev->dev, fbdata->base); }
>>> +
>>> +static int intelvipfb_of_remove(struct platform_device *pdev) {
>>> +     return intelvipfb_remove(&pdev->dev); }
>>> +
>>> +/*
>>> + * The name vip-frame-buffer-2.0 is derived from
>>> + * http://www.altera.com/literature/ug/ug_vip.pdf
>>> + * frame buffer IP cores section 14
>>> + */
>>> +
>>> +static const struct of_device_id intelvipfb_of_match[] = {
>>> +     { .compatible = "altr,vip-frame-buffer-2.0" },
>>> +     {},
>>> +};
>>> +
>>> +MODULE_DEVICE_TABLE(of, intelvipfb_of_match);
>>> +
>>> +static struct platform_driver intelvipfb_driver = {
>>> +     .probe = intelvipfb_of_probe,
>>> +     .remove = intelvipfb_of_remove,
>>> +     .driver = {
>>> +             .name = DRIVER_NAME,
>>> +             .of_match_table = intelvipfb_of_match,
>>> +     },
>>> +};
>>> +
>>> +module_platform_driver(intelvipfb_driver);
>>> --
>>> 1.7.1
>>>
>>>
>>> -----Original Message-----
>>> From: Ong, Hean Loong
>>> Sent: Friday, March 31, 2017 5:09 PM
>>> To: Vetter, Daniel <daniel.vetter@intel.com>; airlied@linux.ie
>>> Cc: dri-devel@lists.freedesktop.org
>>> Subject: DRM Display driver for Intel FPGA Video and Image Processing
>>> Suite
>>>
>>> Hi,
>>>
>>> I would like to upstream the attached Intel FPGA Video and Image
>>> Processing Suite. The attached patch supports the Intel Arria10
>>> devkit and its variants. The purpose of the patch is to enable the
>>> FPGA driven display designed from the Intel Quartus FPGA design
>>> suite.
>>>
>>> The driver is required as part of the Intel Arria10 devkit reference
>>> design. The driver was tested on:
>>> - The Open Embedded Angstrom Distro.
>>> - The matchbox-terminal and window-manager was used for functional
>>> testing
>>>
>>> Current the intention of the driver is meant to validate the FPGA
>>> designs on the Arria10 devkit for Display Port connecter. We have not
>>> verified its performance of or stability in 3D acceleration or other
>>> non Intel FPGA hardware
>>>
>>> BR
>>>
>>> Hean Loong
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>
>
>
>--
>Daniel Vetter
>Software Engineer, Intel Corporation
>+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: DRM Display driver for Intel FPGA Video and Image Processing Suite
  2017-04-08  5:41       ` Ong, Hean Loong
@ 2017-04-08 16:31         ` Daniel Vetter
  2017-04-10  7:49           ` Ong, Hean Loong
  0 siblings, 1 reply; 9+ messages in thread
From: Daniel Vetter @ 2017-04-08 16:31 UTC (permalink / raw)
  To: Ong, Hean Loong; +Cc: Vetter, Daniel, dri-devel

On Sat, Apr 8, 2017 at 7:41 AM, Ong, Hean Loong
<hean.loong.ong@intel.com> wrote:
> Hi Daniel
>
> Thanks for the time and patience for reviewing my changes. I would ensure that subsequent patches will not have the same mail problems.
>
> I have some question on the validation methods. Since my drivers are processing the images with an FPGA would running the tests with https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#testing-and-validation be relevant?

igt testcases automatically skip when they don't apply for a given
platform/driver. They might need some bugfixes if your driver is a
completely new case, but it should work.

> The display images are streamed to the monitor via a Display Port connector thus I don' t think it is virtual. The FPGA is programmed to run with a proprietary Display Port IP. The driver just feeds it with display data.

Well, it looked like a virtual driver (since the real DP handling is
somewhere else like you explain). And since it works like a virtual
driver we could extract a helper library to reduce duplicated code.
Virtual driver here means "just feeds display data to something else
that handles the real output handling duties". That applies to
virtualized gpus, but also to your case here.

Btw a small ascii-art block diagram for your driver hw architecture to
explain stuff like this would be awesome (but it either into a code
comment or into the commit message).

> I would take your advice in implementing it in the small drivers, but since its new are there any special cases that I would have to look out for in implementing this driver in the drm-misc ?

Small drivers is only about how to maintain it once it's merged, not
about the code itself. We assume/hope that people who submit drivers
stay around for helping maintaining it going forward (but if that
doesn't happen, also no big deal).
-Daniel

>
>>-----Original Message-----
>>From: daniel.vetter@ffwll.ch [mailto:daniel.vetter@ffwll.ch] On Behalf Of Daniel
>>Vetter
>>Sent: Saturday, April 8, 2017 12:32 AM
>>To: Ong, Hean Loong <hean.loong.ong@intel.com>
>>Cc: Vetter, Daniel <daniel.vetter@intel.com>; airlied@linux.ie; dri-
>>devel@lists.freedesktop.org
>>Subject: Re: DRM Display driver for Intel FPGA Video and Image Processing Suite
>>
>>On Thu, Apr 6, 2017 at 8:29 AM, Ong, Hean Loong <hean.loong.ong@intel.com>
>>wrote:
>>> Hi All,
>>>
>>> Any comments for the patch below?
>>
>>Seems the same version that I already reviewed. My comment about not sending
>>inline was more for the next version, especially once it's about applying the
>>patch, attached patches are a bit of a pain (since they break the tooling here).
>>-Daniel
>>>
>>> Thanks
>>>
>>> Hean Loong
>>>
>>> On Tue, 2017-04-04 at 04:01 +0000, Ong, Hean Loong wrote:
>>>> Hi All,
>>>>
>>>> Apologies for the attachment earlier. Below are the inline changes
>>>> for the patch
>>>>
>>>> From 0de293e3646a1780ed603cf8e1f2a19d9aebbe83 Mon Sep 17 00:00:00
>>>> 2001
>>>> From: Ong, Hean Loong <hean.loong.ong@intel.com>
>>>> Date: Thu, 30 Mar 2017 18:02:22 +0800
>>>> Subject: [PATCHv0] Intel FPGA Video and Image Processing Suite Frame
>>>> Buffer II driver
>>>>
>>>> Signed-off-by: Ong, Hean Loong <hean.loong.ong@intel.com>
>>>> ---
>>>>  drivers/gpu/drm/Kconfig               |    2 +
>>>>  drivers/gpu/drm/Makefile              |    1 +
>>>>  drivers/gpu/drm/ivip/Kconfig          |   22 ++++
>>>>  drivers/gpu/drm/ivip/Makefile         |    9 ++
>>>>  drivers/gpu/drm/ivip/intel_vip_conn.c |  145 ++++++++++++++++++++++
>>>> drivers/gpu/drm/ivip/intel_vip_core.c |  215
>>>> +++++++++++++++++++++++++++++++++
>>>>  drivers/gpu/drm/ivip/intel_vip_crtc.c |  161
>>>> ++++++++++++++++++++++++
>>>>  drivers/gpu/drm/ivip/intel_vip_drv.h  |   55 +++++++++
>>>>  drivers/gpu/drm/ivip/intel_vip_of.c   |  146 ++++++++++++++++++++++
>>>>  9 files changed, 756 insertions(+), 0 deletions(-)  create mode
>>>> 100644 drivers/gpu/drm/ivip/Kconfig  create mode 100644
>>>> drivers/gpu/drm/ivip/Makefile  create mode 100644
>>>> drivers/gpu/drm/ivip/intel_vip_conn.c
>>>>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_core.c
>>>>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_crtc.c
>>>>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_drv.h
>>>>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_of.c
>>>>
>>>> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index
>>>> ebfe840..c487507 100644
>>>> --- a/drivers/gpu/drm/Kconfig
>>>> +++ b/drivers/gpu/drm/Kconfig
>>>> @@ -167,6 +167,8 @@ source "drivers/gpu/drm/nouveau/Kconfig"
>>>>
>>>>  source "drivers/gpu/drm/i915/Kconfig"
>>>>
>>>> +source "drivers/gpu/drm/ivip/Kconfig"
>>>> +
>>>>  config DRM_VGEM
>>>>       tristate "Virtual GEM provider"
>>>>       depends on DRM
>>>> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
>>>> index b9ae428..945cf53 100644
>>>> --- a/drivers/gpu/drm/Makefile
>>>> +++ b/drivers/gpu/drm/Makefile
>>>> @@ -52,6 +52,7 @@ obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/
>>>>  obj-$(CONFIG_DRM_MGA)        += mga/
>>>>  obj-$(CONFIG_DRM_I810)       += i810/
>>>>  obj-$(CONFIG_DRM_I915)       += i915/
>>>> +obj-$(CONFIG_DRM_IVIP)       += ivip/
>>>>  obj-$(CONFIG_DRM_MGAG200) += mgag200/
>>>>  obj-$(CONFIG_DRM_VC4)  += vc4/
>>>>  obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus/ diff --git
>>>> a/drivers/gpu/drm/ivip/Kconfig b/drivers/gpu/drm/ivip/Kconfig new
>>>> file mode 100644 index 0000000..ddf3cb5
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/ivip/Kconfig
>>>> @@ -0,0 +1,22 @@
>>>> +config DRM_IVIP
>>>> +        tristate "Intel FGPA Video and Image Processing"
>>>> +        depends on DRM
>>>> +        select DRM_GEM_CMA_HELPER
>>>> +        select DRM_KMS_HELPER
>>>> +        select DRM_KMS_FB_HELPER
>>>> +        select DRM_KMS_CMA_HELPER
>>>> +        help
>>>> +                Choose this option if you have a Intel FPGA Arria 10
>>>> system
>>>> +                and above with a Display Port IP. This does not
>>>> support legacy
>>>> +                Intel FPGA Cyclone V display port. Currently only
>>>> single frame
>>>> +                buffer is supported. Note that ACPI and X_86
>>>> architecture is yet
>>>> +                to be supported.
>>>> +
>>>> +config DRM_IVIP_OF
>>>> +        tristate "Intel FGPA Video and Image Processing Open
>>>> Firmware Systems"
>>>> +        depends on DRM_IVIP && OF
>>>> +        help
>>>> +                Choose this option if the Intel FPGA system is using
>>>> Open
>>>> +                Firmware systems (Arria 10). If M is selected the
>>>> module would
>>>> +                be called ivip.
>>>> +
>>>> diff --git a/drivers/gpu/drm/ivip/Makefile
>>>> b/drivers/gpu/drm/ivip/Makefile new file mode 100644 index
>>>> 0000000..7be1e99
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/ivip/Makefile
>>>> @@ -0,0 +1,9 @@
>>>> +#
>>>> +# Makefile for the drm device driver.  This driver provides support
>>>> for the
>>>> +# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
>>>> +
>>>> +ccflags-y := -Iinclude/drm
>>>> +
>>>> +obj-$(CONFIG_DRM_IVIP_OF) += ivip.o
>>>> +ivip-objs := intel_vip_of.o intel_vip_core.o \ intel_vip_conn.o
>>>> +intel_vip_crtc.o
>>>> diff --git a/drivers/gpu/drm/ivip/intel_vip_conn.c
>>>> b/drivers/gpu/drm/ivip/intel_vip_conn.c
>>>> new file mode 100644
>>>> index 0000000..89ab587
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/ivip/intel_vip_conn.c
>>>> @@ -0,0 +1,145 @@
>>>> +/*
>>>> + * intel_vip_conn.c -- Intel Video and Image Processing(VIP)
>>>> + * Frame Buffer II driver
>>>> + *
>>>> + * This driver supports the Intel VIP Frame Reader component.
>>>> + * More info on the hardware can be found in the Intel Video
>>>> + * and Image Processing Suite User Guide at this address
>>>> + * http://www.altera.com/literature/ug/ug_vip.pdf.
>>>> + *
>>>> + * 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.
>>>> + *
>>>> + * 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.
>>>> + *
>>>> + * Authors:
>>>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>>>> + *
>>>> + */
>>>> +
>>>> +#include <linux/init.h>
>>>> +#include <linux/kernel.h>
>>>> +#include <drm/drm_atomic_helper.h>
>>>> +#include <drm/drm_crtc_helper.h>
>>>> +#include <drm/drm_encoder_slave.h>
>>>> +#include <drm/drm_plane_helper.h>
>>>> +
>>>> +static enum drm_connector_status
>>>> +intelvipfb_drm_connector_detect(struct drm_connector *connector,
>>>> bool force)
>>>> +{
>>>> +     return connector_status_connected; }
>>>> +
>>>> +static void intelvipfb_drm_connector_destroy(struct drm_connector
>>>> *connector)
>>>> +{
>>>> +     drm_connector_unregister(connector);
>>>> +     drm_connector_cleanup(connector); }
>>>> +
>>>> +static const struct drm_connector_funcs
>>>> intelvipfb_drm_connector_funcs = {
>>>> +     .dpms = drm_helper_connector_dpms,
>>>> +     .reset = drm_atomic_helper_connector_reset,
>>>> +     .detect = intelvipfb_drm_connector_detect,
>>>> +     .fill_modes = drm_helper_probe_single_connector_modes,
>>>> +     .destroy = intelvipfb_drm_connector_destroy,
>>>> +     .atomic_duplicate_state =
>>>> drm_atomic_helper_connector_duplicate_state,
>>>> +     .atomic_destroy_state =
>>>> drm_atomic_helper_connector_destroy_state,
>>>> +};
>>>> +
>>>> +static int intelvipfb_drm_connector_get_modes(struct drm_connector
>>>> *connector)
>>>> +{
>>>> +     struct drm_device *drm = connector->dev;
>>>> +     int count;
>>>> +
>>>> +     count = drm_add_modes_noedid(connector, drm-
>>>> >mode_config.max_width,
>>>> +                                  drm->mode_config.max_height);
>>>> +     drm_set_preferred_mode(connector, drm-
>>>> >mode_config.max_width,
>>>> +                            drm->mode_config.max_height);
>>>> +     return count;
>>>> +}
>>>> +
>>>> +static const struct drm_connector_helper_funcs
>>>> +intelvipfb_drm_connector_helper_funcs = {
>>>> +     .get_modes = intelvipfb_drm_connector_get_modes,
>>>> +};
>>>> +
>>>> +static const struct drm_encoder_funcs intelvipfb_drm_encoder_funcs =
>>>> +{
>>>> +     .destroy = drm_encoder_cleanup, };
>>>> +
>>>> +static void intelvipfb_mode_set(struct drm_encoder *encoder,
>>>> +                             struct drm_display_mode *mode,
>>>> +                             struct drm_display_mode
>>>> *adjusted_mode)
>>>> +{
>>>> +     /* do nothing */
>>>> +}
>>>> +
>>>> +static void intelvipfb_nop(struct drm_encoder *encoder) {
>>>> +     /* do nothing */
>>>> +}
>>>> +
>>>> +static const struct drm_encoder_helper_funcs i
>>>> +intelvipfb_drm_encoder_helper = {
>>>> +     .mode_set = intelvipfb_mode_set,
>>>> +     .enable = intelvipfb_nop,
>>>> +     .disable = intelvipfb_nop,
>>>> +};
>>>> +
>>>> +int intelvipfb_drm_conn_init(struct drm_device *drm) {
>>>> +     struct drm_encoder_slave *encoder;
>>>> +     struct drm_connector *conn;
>>>> +     int ret;
>>>> +
>>>> +     encoder = devm_kzalloc(drm->dev, sizeof(*encoder),
>>>> GFP_KERNEL);
>>>> +     if (!encoder)
>>>> +             return -ENOMEM;
>>>> +
>>>> +     encoder->base.possible_crtcs = 1;
>>>> +     encoder->base.possible_clones = 0;
>>>> +
>>>> +     ret = drm_encoder_init(drm, &encoder->base,
>>>> +                            &intelvipfb_drm_encoder_funcs,
>>>> +                            DRM_MODE_ENCODER_VIRTUAL, NULL);
>>>> +     if (ret)
>>>> +             return ret;
>>>> +
>>>> +     drm_encoder_helper_add(&encoder->base,
>>>> &intelvipfb_drm_encoder_helper);
>>>> +
>>>> +     conn = devm_kzalloc(drm->dev, sizeof(*conn), GFP_KERNEL);
>>>> +     if (IS_ERR(conn))
>>>> +             return PTR_ERR(conn);
>>>> +
>>>> +     ret = drm_connector_init(drm, conn,
>>>> &intelvipfb_drm_connector_funcs,
>>>> +                              DRM_MODE_CONNECTOR_DisplayPort);
>>>> +     if (ret < 0) {
>>>> +             dev_err(drm->dev, "failed to initialize drm
>>>> connector\n");
>>>> +             ret = -ENOMEM;
>>>> +             goto error_encoder_cleanup;
>>>> +     }
>>>> +
>>>> +     drm_connector_helper_add(conn,
>>>> &intelvipfb_drm_connector_helper_funcs);
>>>> +
>>>> +     ret = drm_mode_connector_attach_encoder(conn, &encoder-
>>>> >base);
>>>> +     if (ret < 0) {
>>>> +             dev_err(drm->dev, "could not attach connector to
>>>> encoder\n");
>>>> +             drm_connector_unregister(conn);
>>>> +             goto error_connector_cleanup;
>>>> +     }
>>>> +
>>>> +     return 0;
>>>> +
>>>> +error_connector_cleanup:
>>>> +     drm_connector_cleanup(conn);
>>>> +
>>>> +error_encoder_cleanup:
>>>> +     drm_encoder_cleanup(&encoder->base);
>>>> +
>>>> +     return ret;
>>>> +}
>>>> diff --git a/drivers/gpu/drm/ivip/intel_vip_core.c
>>>> b/drivers/gpu/drm/ivip/intel_vip_core.c
>>>> new file mode 100644
>>>> index 0000000..3001ad0
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/ivip/intel_vip_core.c
>>>> @@ -0,0 +1,215 @@
>>>> +/*
>>>> + * intel_vip_core.c -- Intel Video and Image Processing(VIP)
>>>> + * Frame Buffer II driver
>>>> + *
>>>> + * This driver supports the Intel VIP Frame Reader component.
>>>> + * More info on the hardware can be found in the Intel Video
>>>> + * and Image Processing Suite User Guide at this address
>>>> + * http://www.altera.com/literature/ug/ug_vip.pdf.
>>>> + *
>>>> + * 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.
>>>> + *
>>>> + * 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.
>>>> + *
>>>> + * Authors:
>>>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>>>> + *
>>>> + */
>>>> +
>>>> +#include <linux/init.h>
>>>> +#include <linux/kernel.h>
>>>> +#include <linux/module.h>
>>>> +
>>>> +#include <drm/drmP.h>
>>>> +#include <drm/drm_atomic.h>
>>>> +#include <drm/drm_atomic_helper.h>
>>>> +#include <drm/drm_crtc_helper.h>
>>>> +#include <drm/drm_fb_helper.h>
>>>> +#include <drm/drm_fb_cma_helper.h>
>>>> +#include <drm/drm_gem_cma_helper.h>
>>>> +#include <drm/drm_of.h>
>>>> +
>>>> +#include "intel_vip_drv.h"
>>>> +
>>>> +static const struct file_operations intelvipfb_drm_fops = {
>>>> +     .owner          = THIS_MODULE,
>>>> +     .open           = drm_open,
>>>> +     .release        = drm_release,
>>>> +     .unlocked_ioctl = drm_ioctl,
>>>> +     .poll           = drm_poll,
>>>> +     .read           = drm_read,
>>>> +     .llseek         = no_llseek,
>>>> +     .mmap           = drm_gem_cma_mmap,
>>>> +};
>>>> +
>>>> +static void intelvipfb_lastclose(struct drm_device *drm) {
>>>> +     struct intelvipfb_priv *fbpriv = drm->dev_private;
>>>> +
>>>> +     drm_fbdev_cma_restore_mode(fbpriv->fbcma);
>>>> +}
>>>> +
>>>> +static struct drm_driver intelvipfb_drm = {
>>>> +     .driver_features =
>>>> +         DRIVER_GEM | DRIVER_PRIME |
>>>> +         DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC,
>>>> +     .gem_free_object_unlocked = drm_gem_cma_free_object,
>>>> +     .gem_vm_ops = &drm_gem_cma_vm_ops,
>>>> +     .dumb_create = drm_gem_cma_dumb_create,
>>>> +     .dumb_map_offset = drm_gem_cma_dumb_map_offset,
>>>> +     .dumb_destroy = drm_gem_dumb_destroy,
>>>> +     .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
>>>> +     .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
>>>> +     .gem_prime_export = drm_gem_prime_export,
>>>> +     .gem_prime_import = drm_gem_prime_import,
>>>> +     .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
>>>> +     .gem_prime_import_sg_table =
>>>> drm_gem_cma_prime_import_sg_table,
>>>> +     .gem_prime_vmap = drm_gem_cma_prime_vmap,
>>>> +     .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
>>>> +     .gem_prime_mmap = drm_gem_cma_prime_mmap,
>>>> +     .name = DRIVER_NAME,
>>>> +     .date = "20170329",
>>>> +     .desc = "Intel FPGA VIP SUITE",
>>>> +     .major = 1,
>>>> +     .minor = 0,
>>>> +     .patchlevel = 0,
>>>> +     .lastclose = intelvipfb_lastclose,
>>>> +     .fops = &intelvipfb_drm_fops,
>>>> +};
>>>> +
>>>> +static void intelvipfb_start_hw(void __iomem *base, resource_size_t
>>>> addr)
>>>> +{
>>>> +     /*
>>>> +      * The frameinfo variable has to correspond to the size of
>>>> the VIP Suite
>>>> +      * Frame Reader register 7 which will determine the maximum
>>>> size used
>>>> +      * in this frameinfo
>>>> +      */
>>>> +
>>>> +     u32 frameinfo;
>>>> +
>>>> +     frameinfo =
>>>> +             readl(base + INTELVIPFB_FRAME_READER) & 0x00ffffff;
>>>> +
>>>> +     writel(frameinfo, base + INTELVIPFB_FRAME_INFO);
>>>> +
>>>> +     writel(addr, base + INTELVIPFB_FRAME_START);
>>>> +     /* Finally set the control register to 1 to start streaming
>>>> */
>>>> +     writel(1, base + INTELVIPFB_CONTROL); }
>>>> +
>>>> +static void intelvipfb_disable_hw(void __iomem *base) {
>>>> +     /* set the control register to 0 to stop streaming */
>>>> +     writel(0, base + INTELVIPFB_CONTROL); }
>>>> +
>>>> +static void intelvipfb_output_poll_changed(struct drm_device *drm) {
>>>> +     struct intelvipfb_priv *fbpriv = drm->dev_private;
>>>> +
>>>> +     drm_fbdev_cma_hotplug_event(fbpriv->fbcma);
>>>> +}
>>>> +
>>>> +static const struct drm_mode_config_funcs
>>>> intelvipfb_mode_config_funcs = {
>>>> +     .fb_create = drm_fb_cma_create,
>>>> +     .output_poll_changed = intelvipfb_output_poll_changed,
>>>> +     .atomic_check = drm_atomic_helper_check,
>>>> +     .atomic_commit = drm_atomic_helper_commit, };
>>>> +
>>>> +static struct drm_mode_config_helper_funcs
>>>> intelvipfb_mode_config_helpers = {
>>>> +     .atomic_commit_tail = drm_atomic_helper_commit_tail, };
>>>> +
>>>> +static void intelvipfb_setup_mode_config(struct drm_device *drm,
>>>> +                                      struct fb_info *info) {
>>>> +     drm_mode_config_init(drm);
>>>> +     drm->mode_config.min_width = 0;
>>>> +     drm->mode_config.min_height = 0;
>>>> +     drm->mode_config.max_width = info->var.xres;
>>>> +     drm->mode_config.max_height = info->var.yres;
>>>> +     drm->mode_config.preferred_depth = 32;
>>>> +     drm->mode_config.funcs = &intelvipfb_mode_config_funcs;
>>>> +     drm->mode_config.helper_private =
>>>> &intelvipfb_mode_config_helpers;
>>>> +}
>>>> +
>>>> +int intelvipfb_probe(struct device *dev, void __iomem *base) {
>>>> +     int retval;
>>>> +     struct drm_device *drm;
>>>> +     struct intelvipfb_priv *fbpriv = dev_get_drvdata(dev);
>>>> +     struct fb_info *info = &fbpriv->info;
>>>> +
>>>> +     /*setup DRM */
>>>> +     drm = drm_dev_alloc(&intelvipfb_drm, dev);
>>>> +     if (IS_ERR(drm))
>>>> +             return PTR_ERR(drm);
>>>> +
>>>> +     drm->dev_private = fbpriv;
>>>> +
>>>> +     dev_set_drvdata(dev, drm);
>>>> +
>>>> +     intelvipfb_setup_mode_config(drm, info);
>>>> +
>>>> +     retval = dma_set_mask_and_coherent(drm->dev,
>>>> DMA_BIT_MASK(32));
>>>> +     if (retval)
>>>> +             return -ENODEV;
>>>> +
>>>> +     retval = intelvipfb_setup_crtc(drm);
>>>> +     if (retval < 0)
>>>> +             return -ENODEV;
>>>> +
>>>> +     retval = intelvipfb_drm_conn_init(drm);
>>>> +     if (retval)
>>>> +             return -ENOMEM;
>>>> +
>>>> +     drm_mode_config_reset(drm);
>>>> +
>>>> +     fbpriv->fbcma = drm_fbdev_cma_init(drm, PREF_BPP,
>>>> +                                                     CRTC_NUM,
>>>> CONN_NUM);
>>>> +     if (!fbpriv->fbcma) {
>>>> +             fbpriv->fbcma = NULL;
>>>> +             return -ENODEV;
>>>> +     }
>>>> +
>>>> +     intelvipfb_start_hw(base, drm->mode_config.fb_base);
>>>> +
>>>> +     drm_kms_helper_poll_init(drm);
>>>> +
>>>> +     drm_dev_register(drm, 0);
>>>> +
>>>> +     return retval;
>>>> +}
>>>> +EXPORT_SYMBOL_GPL(intelvipfb_probe);
>>>> +
>>>> +int intelvipfb_remove(struct device *dev) {
>>>> +     struct drm_device *drm = dev_get_drvdata(dev);
>>>> +     struct intelvipfb_priv *fbpriv = drm->dev_private;
>>>> +
>>>> +     drm_dev_unregister(drm);
>>>> +
>>>> +     drm_kms_helper_poll_fini(drm);
>>>> +     drm_fbdev_cma_fini(fbpriv->fbcma);
>>>> +
>>>> +     intelvipfb_disable_hw(fbpriv->base);
>>>> +
>>>> +drm_mode_config_cleanup(drm);
>>>> +
>>>> +drm_dev_unref(drm);
>>>> +
>>>> +devm_kfree(dev, fbpriv);
>>>> +
>>>> +     return 0;
>>>> +}
>>>> +EXPORT_SYMBOL_GPL(intelvipfb_remove);
>>>> +
>>>> +MODULE_AUTHOR("Ong, Hean-Loong <hean.loong.ong@intel.com>");
>>>> +MODULE_DESCRIPTION("Intel VIP Frame Buffer II driver");
>>>> +MODULE_LICENSE("GPL v2");
>>>> diff --git a/drivers/gpu/drm/ivip/intel_vip_crtc.c
>>>> b/drivers/gpu/drm/ivip/intel_vip_crtc.c
>>>> new file mode 100644
>>>> index 0000000..97a3954
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/ivip/intel_vip_crtc.c
>>>> @@ -0,0 +1,161 @@
>>>> +/*
>>>> + * intel_vip_crtc.c -- Intel Video and Image Processing(VIP)
>>>> + * Frame Buffer II driver
>>>> + *
>>>> + * This driver supports the Intel VIP Frame Reader component.
>>>> + * More info on the hardware can be found in the Intel Video
>>>> + * and Image Processing Suite User Guide at this address
>>>> + * http://www.altera.com/literature/ug/ug_vip.pdf.
>>>> + *
>>>> + * 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.
>>>> + *
>>>> + * 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.
>>>> + *
>>>> + * Authors:
>>>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>>>> + *
>>>> + */
>>>> +
>>>> +#include <linux/init.h>
>>>> +#include <linux/kernel.h>
>>>> +#include <linux/platform_data/simplefb.h>
>>>> +
>>>> +#include <drm/drm_atomic.h>
>>>> +#include <drm/drm_atomic_helper.h>
>>>> +#include <drm/drm_crtc.h>
>>>> +#include <drm/drm_crtc_helper.h>
>>>> +#include <drm/drm_fb_cma_helper.h>
>>>> +#include <drm/drm_gem_cma_helper.h>
>>>> +#include <drm/drm_plane_helper.h>
>>>> +
>>>> +#include "intel_vip_drv.h"
>>>> +
>>>> +static struct simplefb_format intelvipfb_formats[] =
>>>> SIMPLEFB_FORMATS;
>>>> +
>>>> +static void intelvipfb_crtc_destroy(struct drm_crtc *crtc) {
>>>> +     drm_crtc_cleanup(crtc);
>>>> +     kfree(crtc);
>>>> +}
>>>> +
>>>> +static const struct drm_crtc_funcs intelvipfb_crtc_funcs = {
>>>> +     .destroy = intelvipfb_crtc_destroy,
>>>> +     .set_config = drm_atomic_helper_set_config,
>>>> +     .page_flip = drm_atomic_helper_page_flip,
>>>> +     .reset = drm_atomic_helper_crtc_reset,
>>>> +     .atomic_duplicate_state =
>>>> drm_atomic_helper_crtc_duplicate_state,
>>>> +     .atomic_destroy_state =
>>>> drm_atomic_helper_crtc_destroy_state,
>>>> +};
>>>> +
>>>> +static void intelvipfb_crtc_atomic_begin(struct drm_crtc *crtc,
>>>> +                                      struct drm_crtc_state
>>>> *state)
>>>> +{
>>>> +     struct drm_pending_vblank_event *event = crtc->state->event;
>>>> +
>>>> +     if (event) {
>>>> +             crtc->state->event = NULL;
>>>> +
>>>> +             spin_lock_irq(&crtc->dev->event_lock);
>>>> +             drm_crtc_send_vblank_event(crtc, event);
>>>> +             spin_unlock_irq(&crtc->dev->event_lock);
>>>> +     }
>>>> +}
>>>> +
>>>> +static void intelvipfb_crtc_nop(struct drm_crtc *crtc) {
>>>> +     /* do nothing */;
>>>> +}
>>>> +
>>>> +static const struct drm_crtc_helper_funcs
>>>> intelvipfb_crtc_helper_funcs = {
>>>> +     .atomic_begin   = intelvipfb_crtc_atomic_begin,
>>>> +     .enable = intelvipfb_crtc_nop,
>>>> +};
>>>> +
>>>> +static void intelvipfb_plane_destroy(struct drm_plane *plane) {
>>>> +     drm_plane_helper_disable(plane);
>>>> +     drm_plane_cleanup(plane);
>>>> +}
>>>> +
>>>> +static const struct drm_plane_funcs intelvipfb_plane_funcs = {
>>>> +     .update_plane           =
>>>> drm_atomic_helper_update_plane,
>>>> +     .disable_plane          =
>>>> drm_atomic_helper_disable_plane,
>>>> +     .destroy                = intelvipfb_plane_destroy,
>>>> +     .reset                  =
>>>> drm_atomic_helper_plane_reset,
>>>> +     .atomic_duplicate_state =
>>>> drm_atomic_helper_plane_duplicate_state,
>>>> +     .atomic_destroy_state   =
>>>> drm_atomic_helper_plane_destroy_state,
>>>> +};
>>>> +
>>>> +static void intelvipfb_plane_atomic_update(struct drm_plane *plane,
>>>> +                                        struct drm_plane_state
>>>> *state)
>>>> +{
>>>> +     struct intelvipfb_priv *fbpriv;
>>>> +     struct drm_gem_cma_object *gem;
>>>> +
>>>> +     if (!plane->state->crtc || !plane->state->fb)
>>>> +             return;
>>>> +
>>>> +     fbpriv = plane->dev->dev_private;
>>>> +     gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
>>>> +     writel(gem->paddr, fbpriv->base + INTELVIPFB_FRAME_START); }
>>>> +
>>>> +static const struct drm_plane_helper_funcs
>>>> intelvipfb_plane_helper_funcs = {
>>>> +     .atomic_update = intelvipfb_plane_atomic_update, };
>>>> +
>>>> +static struct drm_plane *intelvipfb_plane_init(struct drm_device
>>>> *drm)
>>>> +{
>>>> +     struct drm_plane *plane = NULL;
>>>> +     u32 formats[ARRAY_SIZE(intelvipfb_formats)], i;
>>>> +     int ret;
>>>> +
>>>> +     plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
>>>> +     if (!plane)
>>>> +             return ERR_PTR(-ENOMEM);
>>>> +
>>>> +     for (i = 0; i < ARRAY_SIZE(intelvipfb_formats); i++)
>>>> +             formats[i] = intelvipfb_formats[i].fourcc;
>>>> +
>>>> +     ret = drm_universal_plane_init(drm, plane, 0xff,
>>>> +                                    &intelvipfb_plane_funcs,
>>>> +                                    formats, ARRAY_SIZE(formats),
>>>> +                                    DRM_PLANE_TYPE_PRIMARY,
>>>> NULL);
>>>> +     if (ret)
>>>> +             return ERR_PTR(ret);
>>>> +
>>>> +     drm_plane_helper_add(plane, &intelvipfb_plane_helper_funcs);
>>>> +
>>>> +     return plane;
>>>> +}
>>>> +
>>>> +int intelvipfb_setup_crtc(struct drm_device *drm) {
>>>> +     struct drm_crtc *crtc;
>>>> +     struct drm_plane *primary;
>>>> +     int ret;
>>>> +
>>>> +     crtc = kzalloc(sizeof(*crtc), GFP_KERNEL);
>>>> +     if (!crtc)
>>>> +             return -ENOMEM;
>>>> +
>>>> +     primary = intelvipfb_plane_init(drm);
>>>> +     if (IS_ERR(primary))
>>>> +             return PTR_ERR(primary);
>>>> +
>>>> +     ret = drm_crtc_init_with_planes(drm, crtc, primary, NULL,
>>>> +                                     &intelvipfb_crtc_funcs,
>>>> NULL);
>>>> +
>>>> +     if (ret) {
>>>> +             intelvipfb_plane_destroy(primary);
>>>> +             return ret;
>>>> +     }
>>>> +
>>>> +     drm_crtc_helper_add(crtc, &intelvipfb_crtc_helper_funcs);
>>>> +     return 0;
>>>> +}
>>>> diff --git a/drivers/gpu/drm/ivip/intel_vip_drv.h
>>>> b/drivers/gpu/drm/ivip/intel_vip_drv.h
>>>> new file mode 100644
>>>> index 0000000..657f23c
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/ivip/intel_vip_drv.h
>>>> @@ -0,0 +1,55 @@
>>>> +/*
>>>> + * Copyright (C) 2017 Intel Corporation.
>>>> + *
>>>> + * Intel Video and Image Processing(VIP) Frame Buffer II driver.
>>>> + *
>>>> + * 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.
>>>> + *
>>>> + * 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.
>>>> + *
>>>> + * You should have received a copy of the GNU General Public License
>>>> along with
>>>> + * this program.  If not, see <http://www.gnu.org/licenses/>.
>>>> + *
>>>> + * Authors:
>>>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>>>> + *
>>>> + */
>>>> +#ifndef _INTEL_VIP_DRV_H
>>>> +#define _INTEL_VIP_DRV_H
>>>> +#include <linux/io.h>
>>>> +#include <linux/fb.h>
>>>> +
>>>> +#define DRIVER_NAME  "intelvipfb"
>>>> +#define BYTES_PER_PIXEL      4
>>>> +#define PREF_BPP             32
>>>> +#define CRTC_NUM             1
>>>> +#define CONN_NUM             1
>>>> +
>>>> +/* control registers */
>>>> +#define INTELVIPFB_CONTROL           0
>>>> +#define INTELVIPFB_STATUS            0x4
>>>> +#define INTELVIPFB_INTERRUPT         0x8
>>>> +#define INTELVIPFB_FRAME_COUNTER     0xC
>>>> +#define INTELVIPFB_FRAME_DROP                0x10
>>>> +#define INTELVIPFB_FRAME_INFO                0x14
>>>> +#define INTELVIPFB_FRAME_START               0x18
>>>> +#define INTELVIPFB_FRAME_READER              0x1C
>>>> +
>>>> +int intelvipfb_probe(struct device *dev, void __iomem *base); int
>>>> +intelvipfb_remove(struct device *dev); int
>>>> +intelvipfb_setup_crtc(struct drm_device *drm); int
>>>> +intelvipfb_drm_conn_init(struct drm_device *drm);
>>>> +
>>>> +struct intelvipfb_priv {
>>>> +     struct drm_fbdev_cma *fbcma;
>>>> +     struct drm_device *drm;
>>>> +     struct fb_info info;
>>>> +     void    __iomem         *base;
>>>> +};
>>>> +
>>>> +#endif
>>>> diff --git a/drivers/gpu/drm/ivip/intel_vip_of.c
>>>> b/drivers/gpu/drm/ivip/intel_vip_of.c
>>>> new file mode 100644
>>>> index 0000000..17dff36
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/ivip/intel_vip_of.c
>>>> @@ -0,0 +1,146 @@
>>>> +/*
>>>> + * intel_vip_of.c -- Intel Video and Image Processing(VIP)
>>>> + * Frame Buffer II driver
>>>> + *
>>>> + * This driver supports the Intel VIP Frame Reader component.
>>>> + * More info on the hardware can be found in the Intel Video
>>>> + * and Image Processing Suite User Guide at this address
>>>> + * http://www.altera.com/literature/ug/ug_vip.pdf.
>>>> + *
>>>> + * 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.
>>>> + *
>>>> + * 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.
>>>> + *
>>>> + * Authors:
>>>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>>>> + *
>>>> + */
>>>> +
>>>> +#include <linux/fb.h>
>>>> +#include <linux/init.h>
>>>> +#include <linux/kernel.h>
>>>> +#include <linux/module.h>
>>>> +#include <linux/platform_device.h>
>>>> +
>>>> +#include <drm/drm_fb_helper.h>
>>>> +#include "intel_vip_drv.h"
>>>> +
>>>> +/*
>>>> + * Setting up information derived from OF Device Tree Nodes
>>>> + * max-width, max-height, bits per pixel, memory port width  */
>>>> +
>>>> +static int intelvipfb_of_setup(struct intelvipfb_priv *fbdata,
>>>> +                            struct platform_device *pdev) {
>>>> +     int ret;
>>>> +     int mem_word_width;
>>>> +     u32 bits_per_color;
>>>> +     struct device_node *np = pdev->dev.of_node;
>>>> +
>>>> +     ret = of_property_read_u32(np, "altr,max-width",
>>>> +                                &fbdata->info.var.xres);
>>>> +     if (ret) {
>>>> +             dev_err(&pdev->dev,
>>>> +                     "Missing required parameter 'altr,max-
>>>> width'");
>>>> +             return ret;
>>>> +     }
>>>> +     fbdata->info.var.xres_virtual = fbdata->info.var.xres;
>>>> +
>>>> +     ret = of_property_read_u32(np, "altr,max-height",
>>>> +                                &fbdata->info.var.yres);
>>>> +     if (ret) {
>>>> +             dev_err(&pdev->dev,
>>>> +                     "Missing required parameter 'altr,max-
>>>> height'");
>>>> +             return ret;
>>>> +     }
>>>> +     fbdata->info.var.yres_virtual = fbdata->info.var.yres;
>>>> +
>>>> +     ret = of_property_read_u32(np, "altr,bits-per-symbol",
>>>> &bits_per_color);
>>>> +     if (ret) {
>>>> +             dev_err(&pdev->dev,
>>>> +                     "Missing required parameter 'altr,bits-per-
>>>> symbol'");
>>>> +             return ret;
>>>> +     }
>>>> +
>>>> +     fbdata->info.var.bits_per_pixel = bits_per_color *
>>>> BYTES_PER_PIXEL;
>>>> +
>>>> +     ret = of_property_read_u32(np, "altr,mem-port-width",
>>>> &mem_word_width);
>>>> +     if (ret) {
>>>> +             dev_err(&pdev->dev,
>>>> +                     "Missing required parameter 'altr,mem-port-
>>>> width '");
>>>> +             return ret;
>>>> +     }
>>>> +
>>>> +     if (!(mem_word_width >= 32 && mem_word_width % 32 == 0)) {
>>>> +             dev_err(&pdev->dev,
>>>> +                     "mem-word-width is set to %i. must be >= 32
>>>> and multiple of 32.",
>>>> +                      mem_word_width);
>>>> +             return -ENODEV;
>>>> +     }
>>>> +
>>>> +     return 0;
>>>> +}
>>>> +
>>>> +static int intelvipfb_of_probe(struct platform_device *pdev) {
>>>> +     int retval;
>>>> +     struct resource *reg_res;
>>>> +     struct intelvipfb_priv *fbdata;
>>>> +
>>>> +     fbdata = devm_kzalloc(&pdev->dev, sizeof(*fbdata),
>>>> GFP_KERNEL);
>>>> +     if (!fbdata)
>>>> +             return -ENOMEM;
>>>> +
>>>> +     reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>> +     if (!reg_res)
>>>> +             return -ENOMEM;
>>>> +
>>>> +     fbdata->base = devm_ioremap_resource(&pdev->dev, reg_res);
>>>> +
>>>> +     if (IS_ERR(fbdata->base)) {
>>>> +             dev_err(&pdev->dev, "devm_ioremap_resource
>>>> failed\n");
>>>> +             retval = PTR_ERR(fbdata->base);
>>>> +             return -ENOMEM;
>>>> +     }
>>>> +
>>>> +     intelvipfb_of_setup(fbdata, pdev);
>>>> +
>>>> +     platform_set_drvdata(pdev, fbdata);
>>>> +
>>>> +     return intelvipfb_probe(&pdev->dev, fbdata->base); }
>>>> +
>>>> +static int intelvipfb_of_remove(struct platform_device *pdev) {
>>>> +     return intelvipfb_remove(&pdev->dev); }
>>>> +
>>>> +/*
>>>> + * The name vip-frame-buffer-2.0 is derived from
>>>> + * http://www.altera.com/literature/ug/ug_vip.pdf
>>>> + * frame buffer IP cores section 14
>>>> + */
>>>> +
>>>> +static const struct of_device_id intelvipfb_of_match[] = {
>>>> +     { .compatible = "altr,vip-frame-buffer-2.0" },
>>>> +     {},
>>>> +};
>>>> +
>>>> +MODULE_DEVICE_TABLE(of, intelvipfb_of_match);
>>>> +
>>>> +static struct platform_driver intelvipfb_driver = {
>>>> +     .probe = intelvipfb_of_probe,
>>>> +     .remove = intelvipfb_of_remove,
>>>> +     .driver = {
>>>> +             .name = DRIVER_NAME,
>>>> +             .of_match_table = intelvipfb_of_match,
>>>> +     },
>>>> +};
>>>> +
>>>> +module_platform_driver(intelvipfb_driver);
>>>> --
>>>> 1.7.1
>>>>
>>>>
>>>> -----Original Message-----
>>>> From: Ong, Hean Loong
>>>> Sent: Friday, March 31, 2017 5:09 PM
>>>> To: Vetter, Daniel <daniel.vetter@intel.com>; airlied@linux.ie
>>>> Cc: dri-devel@lists.freedesktop.org
>>>> Subject: DRM Display driver for Intel FPGA Video and Image Processing
>>>> Suite
>>>>
>>>> Hi,
>>>>
>>>> I would like to upstream the attached Intel FPGA Video and Image
>>>> Processing Suite. The attached patch supports the Intel Arria10
>>>> devkit and its variants. The purpose of the patch is to enable the
>>>> FPGA driven display designed from the Intel Quartus FPGA design
>>>> suite.
>>>>
>>>> The driver is required as part of the Intel Arria10 devkit reference
>>>> design. The driver was tested on:
>>>> - The Open Embedded Angstrom Distro.
>>>> - The matchbox-terminal and window-manager was used for functional
>>>> testing
>>>>
>>>> Current the intention of the driver is meant to validate the FPGA
>>>> designs on the Arria10 devkit for Display Port connecter. We have not
>>>> verified its performance of or stability in 3D acceleration or other
>>>> non Intel FPGA hardware
>>>>
>>>> BR
>>>>
>>>> Hean Loong
>>> _______________________________________________
>>> dri-devel mailing list
>>> dri-devel@lists.freedesktop.org
>>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>>
>>
>>
>>--
>>Daniel Vetter
>>Software Engineer, Intel Corporation
>>+41 (0) 79 365 57 48 - http://blog.ffwll.ch



-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: DRM Display driver for Intel FPGA Video and Image Processing Suite
  2017-04-08 16:31         ` Daniel Vetter
@ 2017-04-10  7:49           ` Ong, Hean Loong
  2017-04-10  7:53             ` Daniel Vetter
  0 siblings, 1 reply; 9+ messages in thread
From: Ong, Hean Loong @ 2017-04-10  7:49 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Vetter, Daniel, Ong, Hean Loong, dri-devel

Thanks again Daniel for the clarification.

However I cannot seem to find the repo for the drm-misc and documentation on how to get it from the main kernel tree.

Could you can give me some pointers on where to get the git tree of the drm-misc for small drivers. Sorry as I am not very familiar with the DRM architecture

>-----Original Message-----
>From: daniel.vetter@ffwll.ch [mailto:daniel.vetter@ffwll.ch] On Behalf Of Daniel
>Vetter
>Sent: Sunday, April 9, 2017 12:31 AM
>To: Ong, Hean Loong <hean.loong.ong@intel.com>
>Cc: Vetter, Daniel <daniel.vetter@intel.com>; airlied@linux.ie; dri-
>devel@lists.freedesktop.org
>Subject: Re: DRM Display driver for Intel FPGA Video and Image Processing Suite
>
>On Sat, Apr 8, 2017 at 7:41 AM, Ong, Hean Loong <hean.loong.ong@intel.com>
>wrote:
>> Hi Daniel
>>
>> Thanks for the time and patience for reviewing my changes. I would ensure that
>subsequent patches will not have the same mail problems.
>>
>> I have some question on the validation methods. Since my drivers are
>processing the images with an FPGA would running the tests with
>https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#testing-and-validation
>be relevant?
>
>igt testcases automatically skip when they don't apply for a given platform/driver.
>They might need some bugfixes if your driver is a completely new case, but it
>should work.
>
>> The display images are streamed to the monitor via a Display Port connector
>thus I don' t think it is virtual. The FPGA is programmed to run with a proprietary
>Display Port IP. The driver just feeds it with display data.
>
>Well, it looked like a virtual driver (since the real DP handling is somewhere else
>like you explain). And since it works like a virtual driver we could extract a helper
>library to reduce duplicated code.
>Virtual driver here means "just feeds display data to something else that handles
>the real output handling duties". That applies to virtualized gpus, but also to your
>case here.
>
>Btw a small ascii-art block diagram for your driver hw architecture to explain stuff
>like this would be awesome (but it either into a code comment or into the commit
>message).
>
>> I would take your advice in implementing it in the small drivers, but since its new
>are there any special cases that I would have to look out for in implementing this
>driver in the drm-misc ?
>
>Small drivers is only about how to maintain it once it's merged, not about the
>code itself. We assume/hope that people who submit drivers stay around for
>helping maintaining it going forward (but if that doesn't happen, also no big deal).
>-Daniel
>
>>
>>>-----Original Message-----
>>>From: daniel.vetter@ffwll.ch [mailto:daniel.vetter@ffwll.ch] On Behalf
>>>Of Daniel Vetter
>>>Sent: Saturday, April 8, 2017 12:32 AM
>>>To: Ong, Hean Loong <hean.loong.ong@intel.com>
>>>Cc: Vetter, Daniel <daniel.vetter@intel.com>; airlied@linux.ie; dri-
>>>devel@lists.freedesktop.org
>>>Subject: Re: DRM Display driver for Intel FPGA Video and Image
>>>Processing Suite
>>>
>>>On Thu, Apr 6, 2017 at 8:29 AM, Ong, Hean Loong
>>><hean.loong.ong@intel.com>
>>>wrote:
>>>> Hi All,
>>>>
>>>> Any comments for the patch below?
>>>
>>>Seems the same version that I already reviewed. My comment about not
>>>sending inline was more for the next version, especially once it's
>>>about applying the patch, attached patches are a bit of a pain (since they break
>the tooling here).
>>>-Daniel
>>>>
>>>> Thanks
>>>>
>>>> Hean Loong
>>>>
>>>> On Tue, 2017-04-04 at 04:01 +0000, Ong, Hean Loong wrote:
>>>>> Hi All,
>>>>>
>>>>> Apologies for the attachment earlier. Below are the inline changes
>>>>> for the patch
>>>>>
>>>>> From 0de293e3646a1780ed603cf8e1f2a19d9aebbe83 Mon Sep 17 00:00:00
>>>>> 2001
>>>>> From: Ong, Hean Loong <hean.loong.ong@intel.com>
>>>>> Date: Thu, 30 Mar 2017 18:02:22 +0800
>>>>> Subject: [PATCHv0] Intel FPGA Video and Image Processing Suite
>>>>> Frame Buffer II driver
>>>>>
>>>>> Signed-off-by: Ong, Hean Loong <hean.loong.ong@intel.com>
>>>>> ---
>>>>>  drivers/gpu/drm/Kconfig               |    2 +
>>>>>  drivers/gpu/drm/Makefile              |    1 +
>>>>>  drivers/gpu/drm/ivip/Kconfig          |   22 ++++
>>>>>  drivers/gpu/drm/ivip/Makefile         |    9 ++
>>>>>  drivers/gpu/drm/ivip/intel_vip_conn.c |  145
>>>>> ++++++++++++++++++++++ drivers/gpu/drm/ivip/intel_vip_core.c |  215
>>>>> +++++++++++++++++++++++++++++++++
>>>>>  drivers/gpu/drm/ivip/intel_vip_crtc.c |  161
>>>>> ++++++++++++++++++++++++
>>>>>  drivers/gpu/drm/ivip/intel_vip_drv.h  |   55 +++++++++
>>>>>  drivers/gpu/drm/ivip/intel_vip_of.c   |  146 ++++++++++++++++++++++
>>>>>  9 files changed, 756 insertions(+), 0 deletions(-)  create mode
>>>>> 100644 drivers/gpu/drm/ivip/Kconfig  create mode 100644
>>>>> drivers/gpu/drm/ivip/Makefile  create mode 100644
>>>>> drivers/gpu/drm/ivip/intel_vip_conn.c
>>>>>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_core.c
>>>>>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_crtc.c
>>>>>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_drv.h
>>>>>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_of.c
>>>>>
>>>>> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
>>>>> index
>>>>> ebfe840..c487507 100644
>>>>> --- a/drivers/gpu/drm/Kconfig
>>>>> +++ b/drivers/gpu/drm/Kconfig
>>>>> @@ -167,6 +167,8 @@ source "drivers/gpu/drm/nouveau/Kconfig"
>>>>>
>>>>>  source "drivers/gpu/drm/i915/Kconfig"
>>>>>
>>>>> +source "drivers/gpu/drm/ivip/Kconfig"
>>>>> +
>>>>>  config DRM_VGEM
>>>>>       tristate "Virtual GEM provider"
>>>>>       depends on DRM
>>>>> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
>>>>> index b9ae428..945cf53 100644
>>>>> --- a/drivers/gpu/drm/Makefile
>>>>> +++ b/drivers/gpu/drm/Makefile
>>>>> @@ -52,6 +52,7 @@ obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/
>>>>>  obj-$(CONFIG_DRM_MGA)        += mga/
>>>>>  obj-$(CONFIG_DRM_I810)       += i810/
>>>>>  obj-$(CONFIG_DRM_I915)       += i915/
>>>>> +obj-$(CONFIG_DRM_IVIP)       += ivip/
>>>>>  obj-$(CONFIG_DRM_MGAG200) += mgag200/
>>>>>  obj-$(CONFIG_DRM_VC4)  += vc4/
>>>>>  obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus/ diff --git
>>>>> a/drivers/gpu/drm/ivip/Kconfig b/drivers/gpu/drm/ivip/Kconfig new
>>>>> file mode 100644 index 0000000..ddf3cb5
>>>>> --- /dev/null
>>>>> +++ b/drivers/gpu/drm/ivip/Kconfig
>>>>> @@ -0,0 +1,22 @@
>>>>> +config DRM_IVIP
>>>>> +        tristate "Intel FGPA Video and Image Processing"
>>>>> +        depends on DRM
>>>>> +        select DRM_GEM_CMA_HELPER
>>>>> +        select DRM_KMS_HELPER
>>>>> +        select DRM_KMS_FB_HELPER
>>>>> +        select DRM_KMS_CMA_HELPER
>>>>> +        help
>>>>> +                Choose this option if you have a Intel FPGA Arria
>>>>> +10
>>>>> system
>>>>> +                and above with a Display Port IP. This does not
>>>>> support legacy
>>>>> +                Intel FPGA Cyclone V display port. Currently only
>>>>> single frame
>>>>> +                buffer is supported. Note that ACPI and X_86
>>>>> architecture is yet
>>>>> +                to be supported.
>>>>> +
>>>>> +config DRM_IVIP_OF
>>>>> +        tristate "Intel FGPA Video and Image Processing Open
>>>>> Firmware Systems"
>>>>> +        depends on DRM_IVIP && OF
>>>>> +        help
>>>>> +                Choose this option if the Intel FPGA system is
>>>>> + using
>>>>> Open
>>>>> +                Firmware systems (Arria 10). If M is selected the
>>>>> module would
>>>>> +                be called ivip.
>>>>> +
>>>>> diff --git a/drivers/gpu/drm/ivip/Makefile
>>>>> b/drivers/gpu/drm/ivip/Makefile new file mode 100644 index
>>>>> 0000000..7be1e99
>>>>> --- /dev/null
>>>>> +++ b/drivers/gpu/drm/ivip/Makefile
>>>>> @@ -0,0 +1,9 @@
>>>>> +#
>>>>> +# Makefile for the drm device driver.  This driver provides
>>>>> +support
>>>>> for the
>>>>> +# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
>>>>> +
>>>>> +ccflags-y := -Iinclude/drm
>>>>> +
>>>>> +obj-$(CONFIG_DRM_IVIP_OF) += ivip.o ivip-objs := intel_vip_of.o
>>>>> +intel_vip_core.o \ intel_vip_conn.o intel_vip_crtc.o
>>>>> diff --git a/drivers/gpu/drm/ivip/intel_vip_conn.c
>>>>> b/drivers/gpu/drm/ivip/intel_vip_conn.c
>>>>> new file mode 100644
>>>>> index 0000000..89ab587
>>>>> --- /dev/null
>>>>> +++ b/drivers/gpu/drm/ivip/intel_vip_conn.c
>>>>> @@ -0,0 +1,145 @@
>>>>> +/*
>>>>> + * intel_vip_conn.c -- Intel Video and Image Processing(VIP)
>>>>> + * Frame Buffer II driver
>>>>> + *
>>>>> + * This driver supports the Intel VIP Frame Reader component.
>>>>> + * More info on the hardware can be found in the Intel Video
>>>>> + * and Image Processing Suite User Guide at this address
>>>>> + * http://www.altera.com/literature/ug/ug_vip.pdf.
>>>>> + *
>>>>> + * 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.
>>>>> + *
>>>>> + * 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.
>>>>> + *
>>>>> + * Authors:
>>>>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>>>>> + *
>>>>> + */
>>>>> +
>>>>> +#include <linux/init.h>
>>>>> +#include <linux/kernel.h>
>>>>> +#include <drm/drm_atomic_helper.h> #include
>>>>> +<drm/drm_crtc_helper.h> #include <drm/drm_encoder_slave.h>
>>>>> +#include <drm/drm_plane_helper.h>
>>>>> +
>>>>> +static enum drm_connector_status
>>>>> +intelvipfb_drm_connector_detect(struct drm_connector *connector,
>>>>> bool force)
>>>>> +{
>>>>> +     return connector_status_connected; }
>>>>> +
>>>>> +static void intelvipfb_drm_connector_destroy(struct drm_connector
>>>>> *connector)
>>>>> +{
>>>>> +     drm_connector_unregister(connector);
>>>>> +     drm_connector_cleanup(connector); }
>>>>> +
>>>>> +static const struct drm_connector_funcs
>>>>> intelvipfb_drm_connector_funcs = {
>>>>> +     .dpms = drm_helper_connector_dpms,
>>>>> +     .reset = drm_atomic_helper_connector_reset,
>>>>> +     .detect = intelvipfb_drm_connector_detect,
>>>>> +     .fill_modes = drm_helper_probe_single_connector_modes,
>>>>> +     .destroy = intelvipfb_drm_connector_destroy,
>>>>> +     .atomic_duplicate_state =
>>>>> drm_atomic_helper_connector_duplicate_state,
>>>>> +     .atomic_destroy_state =
>>>>> drm_atomic_helper_connector_destroy_state,
>>>>> +};
>>>>> +
>>>>> +static int intelvipfb_drm_connector_get_modes(struct drm_connector
>>>>> *connector)
>>>>> +{
>>>>> +     struct drm_device *drm = connector->dev;
>>>>> +     int count;
>>>>> +
>>>>> +     count = drm_add_modes_noedid(connector, drm-
>>>>> >mode_config.max_width,
>>>>> +                                  drm->mode_config.max_height);
>>>>> +     drm_set_preferred_mode(connector, drm-
>>>>> >mode_config.max_width,
>>>>> +                            drm->mode_config.max_height);
>>>>> +     return count;
>>>>> +}
>>>>> +
>>>>> +static const struct drm_connector_helper_funcs
>>>>> +intelvipfb_drm_connector_helper_funcs = {
>>>>> +     .get_modes = intelvipfb_drm_connector_get_modes,
>>>>> +};
>>>>> +
>>>>> +static const struct drm_encoder_funcs intelvipfb_drm_encoder_funcs
>>>>> += {
>>>>> +     .destroy = drm_encoder_cleanup, };
>>>>> +
>>>>> +static void intelvipfb_mode_set(struct drm_encoder *encoder,
>>>>> +                             struct drm_display_mode *mode,
>>>>> +                             struct drm_display_mode
>>>>> *adjusted_mode)
>>>>> +{
>>>>> +     /* do nothing */
>>>>> +}
>>>>> +
>>>>> +static void intelvipfb_nop(struct drm_encoder *encoder) {
>>>>> +     /* do nothing */
>>>>> +}
>>>>> +
>>>>> +static const struct drm_encoder_helper_funcs i
>>>>> +intelvipfb_drm_encoder_helper = {
>>>>> +     .mode_set = intelvipfb_mode_set,
>>>>> +     .enable = intelvipfb_nop,
>>>>> +     .disable = intelvipfb_nop,
>>>>> +};
>>>>> +
>>>>> +int intelvipfb_drm_conn_init(struct drm_device *drm) {
>>>>> +     struct drm_encoder_slave *encoder;
>>>>> +     struct drm_connector *conn;
>>>>> +     int ret;
>>>>> +
>>>>> +     encoder = devm_kzalloc(drm->dev, sizeof(*encoder),
>>>>> GFP_KERNEL);
>>>>> +     if (!encoder)
>>>>> +             return -ENOMEM;
>>>>> +
>>>>> +     encoder->base.possible_crtcs = 1;
>>>>> +     encoder->base.possible_clones = 0;
>>>>> +
>>>>> +     ret = drm_encoder_init(drm, &encoder->base,
>>>>> +                            &intelvipfb_drm_encoder_funcs,
>>>>> +                            DRM_MODE_ENCODER_VIRTUAL, NULL);
>>>>> +     if (ret)
>>>>> +             return ret;
>>>>> +
>>>>> +     drm_encoder_helper_add(&encoder->base,
>>>>> &intelvipfb_drm_encoder_helper);
>>>>> +
>>>>> +     conn = devm_kzalloc(drm->dev, sizeof(*conn), GFP_KERNEL);
>>>>> +     if (IS_ERR(conn))
>>>>> +             return PTR_ERR(conn);
>>>>> +
>>>>> +     ret = drm_connector_init(drm, conn,
>>>>> &intelvipfb_drm_connector_funcs,
>>>>> +                              DRM_MODE_CONNECTOR_DisplayPort);
>>>>> +     if (ret < 0) {
>>>>> +             dev_err(drm->dev, "failed to initialize drm
>>>>> connector\n");
>>>>> +             ret = -ENOMEM;
>>>>> +             goto error_encoder_cleanup;
>>>>> +     }
>>>>> +
>>>>> +     drm_connector_helper_add(conn,
>>>>> &intelvipfb_drm_connector_helper_funcs);
>>>>> +
>>>>> +     ret = drm_mode_connector_attach_encoder(conn, &encoder-
>>>>> >base);
>>>>> +     if (ret < 0) {
>>>>> +             dev_err(drm->dev, "could not attach connector to
>>>>> encoder\n");
>>>>> +             drm_connector_unregister(conn);
>>>>> +             goto error_connector_cleanup;
>>>>> +     }
>>>>> +
>>>>> +     return 0;
>>>>> +
>>>>> +error_connector_cleanup:
>>>>> +     drm_connector_cleanup(conn);
>>>>> +
>>>>> +error_encoder_cleanup:
>>>>> +     drm_encoder_cleanup(&encoder->base);
>>>>> +
>>>>> +     return ret;
>>>>> +}
>>>>> diff --git a/drivers/gpu/drm/ivip/intel_vip_core.c
>>>>> b/drivers/gpu/drm/ivip/intel_vip_core.c
>>>>> new file mode 100644
>>>>> index 0000000..3001ad0
>>>>> --- /dev/null
>>>>> +++ b/drivers/gpu/drm/ivip/intel_vip_core.c
>>>>> @@ -0,0 +1,215 @@
>>>>> +/*
>>>>> + * intel_vip_core.c -- Intel Video and Image Processing(VIP)
>>>>> + * Frame Buffer II driver
>>>>> + *
>>>>> + * This driver supports the Intel VIP Frame Reader component.
>>>>> + * More info on the hardware can be found in the Intel Video
>>>>> + * and Image Processing Suite User Guide at this address
>>>>> + * http://www.altera.com/literature/ug/ug_vip.pdf.
>>>>> + *
>>>>> + * 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.
>>>>> + *
>>>>> + * 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.
>>>>> + *
>>>>> + * Authors:
>>>>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>>>>> + *
>>>>> + */
>>>>> +
>>>>> +#include <linux/init.h>
>>>>> +#include <linux/kernel.h>
>>>>> +#include <linux/module.h>
>>>>> +
>>>>> +#include <drm/drmP.h>
>>>>> +#include <drm/drm_atomic.h>
>>>>> +#include <drm/drm_atomic_helper.h> #include
>>>>> +<drm/drm_crtc_helper.h> #include <drm/drm_fb_helper.h> #include
>>>>> +<drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
>>>>> +#include <drm/drm_of.h>
>>>>> +
>>>>> +#include "intel_vip_drv.h"
>>>>> +
>>>>> +static const struct file_operations intelvipfb_drm_fops = {
>>>>> +     .owner          = THIS_MODULE,
>>>>> +     .open           = drm_open,
>>>>> +     .release        = drm_release,
>>>>> +     .unlocked_ioctl = drm_ioctl,
>>>>> +     .poll           = drm_poll,
>>>>> +     .read           = drm_read,
>>>>> +     .llseek         = no_llseek,
>>>>> +     .mmap           = drm_gem_cma_mmap,
>>>>> +};
>>>>> +
>>>>> +static void intelvipfb_lastclose(struct drm_device *drm) {
>>>>> +     struct intelvipfb_priv *fbpriv = drm->dev_private;
>>>>> +
>>>>> +     drm_fbdev_cma_restore_mode(fbpriv->fbcma);
>>>>> +}
>>>>> +
>>>>> +static struct drm_driver intelvipfb_drm = {
>>>>> +     .driver_features =
>>>>> +         DRIVER_GEM | DRIVER_PRIME |
>>>>> +         DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC,
>>>>> +     .gem_free_object_unlocked = drm_gem_cma_free_object,
>>>>> +     .gem_vm_ops = &drm_gem_cma_vm_ops,
>>>>> +     .dumb_create = drm_gem_cma_dumb_create,
>>>>> +     .dumb_map_offset = drm_gem_cma_dumb_map_offset,
>>>>> +     .dumb_destroy = drm_gem_dumb_destroy,
>>>>> +     .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
>>>>> +     .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
>>>>> +     .gem_prime_export = drm_gem_prime_export,
>>>>> +     .gem_prime_import = drm_gem_prime_import,
>>>>> +     .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
>>>>> +     .gem_prime_import_sg_table =
>>>>> drm_gem_cma_prime_import_sg_table,
>>>>> +     .gem_prime_vmap = drm_gem_cma_prime_vmap,
>>>>> +     .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
>>>>> +     .gem_prime_mmap = drm_gem_cma_prime_mmap,
>>>>> +     .name = DRIVER_NAME,
>>>>> +     .date = "20170329",
>>>>> +     .desc = "Intel FPGA VIP SUITE",
>>>>> +     .major = 1,
>>>>> +     .minor = 0,
>>>>> +     .patchlevel = 0,
>>>>> +     .lastclose = intelvipfb_lastclose,
>>>>> +     .fops = &intelvipfb_drm_fops, };
>>>>> +
>>>>> +static void intelvipfb_start_hw(void __iomem *base,
>>>>> +resource_size_t
>>>>> addr)
>>>>> +{
>>>>> +     /*
>>>>> +      * The frameinfo variable has to correspond to the size of
>>>>> the VIP Suite
>>>>> +      * Frame Reader register 7 which will determine the maximum
>>>>> size used
>>>>> +      * in this frameinfo
>>>>> +      */
>>>>> +
>>>>> +     u32 frameinfo;
>>>>> +
>>>>> +     frameinfo =
>>>>> +             readl(base + INTELVIPFB_FRAME_READER) & 0x00ffffff;
>>>>> +
>>>>> +     writel(frameinfo, base + INTELVIPFB_FRAME_INFO);
>>>>> +
>>>>> +     writel(addr, base + INTELVIPFB_FRAME_START);
>>>>> +     /* Finally set the control register to 1 to start streaming
>>>>> */
>>>>> +     writel(1, base + INTELVIPFB_CONTROL); }
>>>>> +
>>>>> +static void intelvipfb_disable_hw(void __iomem *base) {
>>>>> +     /* set the control register to 0 to stop streaming */
>>>>> +     writel(0, base + INTELVIPFB_CONTROL); }
>>>>> +
>>>>> +static void intelvipfb_output_poll_changed(struct drm_device *drm) {
>>>>> +     struct intelvipfb_priv *fbpriv = drm->dev_private;
>>>>> +
>>>>> +     drm_fbdev_cma_hotplug_event(fbpriv->fbcma);
>>>>> +}
>>>>> +
>>>>> +static const struct drm_mode_config_funcs
>>>>> intelvipfb_mode_config_funcs = {
>>>>> +     .fb_create = drm_fb_cma_create,
>>>>> +     .output_poll_changed = intelvipfb_output_poll_changed,
>>>>> +     .atomic_check = drm_atomic_helper_check,
>>>>> +     .atomic_commit = drm_atomic_helper_commit, };
>>>>> +
>>>>> +static struct drm_mode_config_helper_funcs
>>>>> intelvipfb_mode_config_helpers = {
>>>>> +     .atomic_commit_tail = drm_atomic_helper_commit_tail, };
>>>>> +
>>>>> +static void intelvipfb_setup_mode_config(struct drm_device *drm,
>>>>> +                                      struct fb_info *info) {
>>>>> +     drm_mode_config_init(drm);
>>>>> +     drm->mode_config.min_width = 0;
>>>>> +     drm->mode_config.min_height = 0;
>>>>> +     drm->mode_config.max_width = info->var.xres;
>>>>> +     drm->mode_config.max_height = info->var.yres;
>>>>> +     drm->mode_config.preferred_depth = 32;
>>>>> +     drm->mode_config.funcs = &intelvipfb_mode_config_funcs;
>>>>> +     drm->mode_config.helper_private =
>>>>> &intelvipfb_mode_config_helpers;
>>>>> +}
>>>>> +
>>>>> +int intelvipfb_probe(struct device *dev, void __iomem *base) {
>>>>> +     int retval;
>>>>> +     struct drm_device *drm;
>>>>> +     struct intelvipfb_priv *fbpriv = dev_get_drvdata(dev);
>>>>> +     struct fb_info *info = &fbpriv->info;
>>>>> +
>>>>> +     /*setup DRM */
>>>>> +     drm = drm_dev_alloc(&intelvipfb_drm, dev);
>>>>> +     if (IS_ERR(drm))
>>>>> +             return PTR_ERR(drm);
>>>>> +
>>>>> +     drm->dev_private = fbpriv;
>>>>> +
>>>>> +     dev_set_drvdata(dev, drm);
>>>>> +
>>>>> +     intelvipfb_setup_mode_config(drm, info);
>>>>> +
>>>>> +     retval = dma_set_mask_and_coherent(drm->dev,
>>>>> DMA_BIT_MASK(32));
>>>>> +     if (retval)
>>>>> +             return -ENODEV;
>>>>> +
>>>>> +     retval = intelvipfb_setup_crtc(drm);
>>>>> +     if (retval < 0)
>>>>> +             return -ENODEV;
>>>>> +
>>>>> +     retval = intelvipfb_drm_conn_init(drm);
>>>>> +     if (retval)
>>>>> +             return -ENOMEM;
>>>>> +
>>>>> +     drm_mode_config_reset(drm);
>>>>> +
>>>>> +     fbpriv->fbcma = drm_fbdev_cma_init(drm, PREF_BPP,
>>>>> +                                                     CRTC_NUM,
>>>>> CONN_NUM);
>>>>> +     if (!fbpriv->fbcma) {
>>>>> +             fbpriv->fbcma = NULL;
>>>>> +             return -ENODEV;
>>>>> +     }
>>>>> +
>>>>> +     intelvipfb_start_hw(base, drm->mode_config.fb_base);
>>>>> +
>>>>> +     drm_kms_helper_poll_init(drm);
>>>>> +
>>>>> +     drm_dev_register(drm, 0);
>>>>> +
>>>>> +     return retval;
>>>>> +}
>>>>> +EXPORT_SYMBOL_GPL(intelvipfb_probe);
>>>>> +
>>>>> +int intelvipfb_remove(struct device *dev) {
>>>>> +     struct drm_device *drm = dev_get_drvdata(dev);
>>>>> +     struct intelvipfb_priv *fbpriv = drm->dev_private;
>>>>> +
>>>>> +     drm_dev_unregister(drm);
>>>>> +
>>>>> +     drm_kms_helper_poll_fini(drm);
>>>>> +     drm_fbdev_cma_fini(fbpriv->fbcma);
>>>>> +
>>>>> +     intelvipfb_disable_hw(fbpriv->base);
>>>>> +
>>>>> +drm_mode_config_cleanup(drm);
>>>>> +
>>>>> +drm_dev_unref(drm);
>>>>> +
>>>>> +devm_kfree(dev, fbpriv);
>>>>> +
>>>>> +     return 0;
>>>>> +}
>>>>> +EXPORT_SYMBOL_GPL(intelvipfb_remove);
>>>>> +
>>>>> +MODULE_AUTHOR("Ong, Hean-Loong <hean.loong.ong@intel.com>");
>>>>> +MODULE_DESCRIPTION("Intel VIP Frame Buffer II driver");
>>>>> +MODULE_LICENSE("GPL v2");
>>>>> diff --git a/drivers/gpu/drm/ivip/intel_vip_crtc.c
>>>>> b/drivers/gpu/drm/ivip/intel_vip_crtc.c
>>>>> new file mode 100644
>>>>> index 0000000..97a3954
>>>>> --- /dev/null
>>>>> +++ b/drivers/gpu/drm/ivip/intel_vip_crtc.c
>>>>> @@ -0,0 +1,161 @@
>>>>> +/*
>>>>> + * intel_vip_crtc.c -- Intel Video and Image Processing(VIP)
>>>>> + * Frame Buffer II driver
>>>>> + *
>>>>> + * This driver supports the Intel VIP Frame Reader component.
>>>>> + * More info on the hardware can be found in the Intel Video
>>>>> + * and Image Processing Suite User Guide at this address
>>>>> + * http://www.altera.com/literature/ug/ug_vip.pdf.
>>>>> + *
>>>>> + * 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.
>>>>> + *
>>>>> + * 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.
>>>>> + *
>>>>> + * Authors:
>>>>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>>>>> + *
>>>>> + */
>>>>> +
>>>>> +#include <linux/init.h>
>>>>> +#include <linux/kernel.h>
>>>>> +#include <linux/platform_data/simplefb.h>
>>>>> +
>>>>> +#include <drm/drm_atomic.h>
>>>>> +#include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h>
>>>>> +#include <drm/drm_crtc_helper.h> #include
>>>>> +<drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
>>>>> +#include <drm/drm_plane_helper.h>
>>>>> +
>>>>> +#include "intel_vip_drv.h"
>>>>> +
>>>>> +static struct simplefb_format intelvipfb_formats[] =
>>>>> SIMPLEFB_FORMATS;
>>>>> +
>>>>> +static void intelvipfb_crtc_destroy(struct drm_crtc *crtc) {
>>>>> +     drm_crtc_cleanup(crtc);
>>>>> +     kfree(crtc);
>>>>> +}
>>>>> +
>>>>> +static const struct drm_crtc_funcs intelvipfb_crtc_funcs = {
>>>>> +     .destroy = intelvipfb_crtc_destroy,
>>>>> +     .set_config = drm_atomic_helper_set_config,
>>>>> +     .page_flip = drm_atomic_helper_page_flip,
>>>>> +     .reset = drm_atomic_helper_crtc_reset,
>>>>> +     .atomic_duplicate_state =
>>>>> drm_atomic_helper_crtc_duplicate_state,
>>>>> +     .atomic_destroy_state =
>>>>> drm_atomic_helper_crtc_destroy_state,
>>>>> +};
>>>>> +
>>>>> +static void intelvipfb_crtc_atomic_begin(struct drm_crtc *crtc,
>>>>> +                                      struct drm_crtc_state
>>>>> *state)
>>>>> +{
>>>>> +     struct drm_pending_vblank_event *event = crtc->state->event;
>>>>> +
>>>>> +     if (event) {
>>>>> +             crtc->state->event = NULL;
>>>>> +
>>>>> +             spin_lock_irq(&crtc->dev->event_lock);
>>>>> +             drm_crtc_send_vblank_event(crtc, event);
>>>>> +             spin_unlock_irq(&crtc->dev->event_lock);
>>>>> +     }
>>>>> +}
>>>>> +
>>>>> +static void intelvipfb_crtc_nop(struct drm_crtc *crtc) {
>>>>> +     /* do nothing */;
>>>>> +}
>>>>> +
>>>>> +static const struct drm_crtc_helper_funcs
>>>>> intelvipfb_crtc_helper_funcs = {
>>>>> +     .atomic_begin   = intelvipfb_crtc_atomic_begin,
>>>>> +     .enable = intelvipfb_crtc_nop, };
>>>>> +
>>>>> +static void intelvipfb_plane_destroy(struct drm_plane *plane) {
>>>>> +     drm_plane_helper_disable(plane);
>>>>> +     drm_plane_cleanup(plane);
>>>>> +}
>>>>> +
>>>>> +static const struct drm_plane_funcs intelvipfb_plane_funcs = {
>>>>> +     .update_plane           =
>>>>> drm_atomic_helper_update_plane,
>>>>> +     .disable_plane          =
>>>>> drm_atomic_helper_disable_plane,
>>>>> +     .destroy                = intelvipfb_plane_destroy,
>>>>> +     .reset                  =
>>>>> drm_atomic_helper_plane_reset,
>>>>> +     .atomic_duplicate_state =
>>>>> drm_atomic_helper_plane_duplicate_state,
>>>>> +     .atomic_destroy_state   =
>>>>> drm_atomic_helper_plane_destroy_state,
>>>>> +};
>>>>> +
>>>>> +static void intelvipfb_plane_atomic_update(struct drm_plane *plane,
>>>>> +                                        struct drm_plane_state
>>>>> *state)
>>>>> +{
>>>>> +     struct intelvipfb_priv *fbpriv;
>>>>> +     struct drm_gem_cma_object *gem;
>>>>> +
>>>>> +     if (!plane->state->crtc || !plane->state->fb)
>>>>> +             return;
>>>>> +
>>>>> +     fbpriv = plane->dev->dev_private;
>>>>> +     gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
>>>>> +     writel(gem->paddr, fbpriv->base + INTELVIPFB_FRAME_START); }
>>>>> +
>>>>> +static const struct drm_plane_helper_funcs
>>>>> intelvipfb_plane_helper_funcs = {
>>>>> +     .atomic_update = intelvipfb_plane_atomic_update, };
>>>>> +
>>>>> +static struct drm_plane *intelvipfb_plane_init(struct drm_device
>>>>> *drm)
>>>>> +{
>>>>> +     struct drm_plane *plane = NULL;
>>>>> +     u32 formats[ARRAY_SIZE(intelvipfb_formats)], i;
>>>>> +     int ret;
>>>>> +
>>>>> +     plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
>>>>> +     if (!plane)
>>>>> +             return ERR_PTR(-ENOMEM);
>>>>> +
>>>>> +     for (i = 0; i < ARRAY_SIZE(intelvipfb_formats); i++)
>>>>> +             formats[i] = intelvipfb_formats[i].fourcc;
>>>>> +
>>>>> +     ret = drm_universal_plane_init(drm, plane, 0xff,
>>>>> +                                    &intelvipfb_plane_funcs,
>>>>> +                                    formats, ARRAY_SIZE(formats),
>>>>> +                                    DRM_PLANE_TYPE_PRIMARY,
>>>>> NULL);
>>>>> +     if (ret)
>>>>> +             return ERR_PTR(ret);
>>>>> +
>>>>> +     drm_plane_helper_add(plane, &intelvipfb_plane_helper_funcs);
>>>>> +
>>>>> +     return plane;
>>>>> +}
>>>>> +
>>>>> +int intelvipfb_setup_crtc(struct drm_device *drm) {
>>>>> +     struct drm_crtc *crtc;
>>>>> +     struct drm_plane *primary;
>>>>> +     int ret;
>>>>> +
>>>>> +     crtc = kzalloc(sizeof(*crtc), GFP_KERNEL);
>>>>> +     if (!crtc)
>>>>> +             return -ENOMEM;
>>>>> +
>>>>> +     primary = intelvipfb_plane_init(drm);
>>>>> +     if (IS_ERR(primary))
>>>>> +             return PTR_ERR(primary);
>>>>> +
>>>>> +     ret = drm_crtc_init_with_planes(drm, crtc, primary, NULL,
>>>>> +                                     &intelvipfb_crtc_funcs,
>>>>> NULL);
>>>>> +
>>>>> +     if (ret) {
>>>>> +             intelvipfb_plane_destroy(primary);
>>>>> +             return ret;
>>>>> +     }
>>>>> +
>>>>> +     drm_crtc_helper_add(crtc, &intelvipfb_crtc_helper_funcs);
>>>>> +     return 0;
>>>>> +}
>>>>> diff --git a/drivers/gpu/drm/ivip/intel_vip_drv.h
>>>>> b/drivers/gpu/drm/ivip/intel_vip_drv.h
>>>>> new file mode 100644
>>>>> index 0000000..657f23c
>>>>> --- /dev/null
>>>>> +++ b/drivers/gpu/drm/ivip/intel_vip_drv.h
>>>>> @@ -0,0 +1,55 @@
>>>>> +/*
>>>>> + * Copyright (C) 2017 Intel Corporation.
>>>>> + *
>>>>> + * Intel Video and Image Processing(VIP) Frame Buffer II driver.
>>>>> + *
>>>>> + * 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.
>>>>> + *
>>>>> + * 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.
>>>>> + *
>>>>> + * You should have received a copy of the GNU General Public
>>>>> + License
>>>>> along with
>>>>> + * this program.  If not, see <http://www.gnu.org/licenses/>.
>>>>> + *
>>>>> + * Authors:
>>>>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>>>>> + *
>>>>> + */
>>>>> +#ifndef _INTEL_VIP_DRV_H
>>>>> +#define _INTEL_VIP_DRV_H
>>>>> +#include <linux/io.h>
>>>>> +#include <linux/fb.h>
>>>>> +
>>>>> +#define DRIVER_NAME  "intelvipfb"
>>>>> +#define BYTES_PER_PIXEL      4
>>>>> +#define PREF_BPP             32
>>>>> +#define CRTC_NUM             1
>>>>> +#define CONN_NUM             1
>>>>> +
>>>>> +/* control registers */
>>>>> +#define INTELVIPFB_CONTROL           0
>>>>> +#define INTELVIPFB_STATUS            0x4
>>>>> +#define INTELVIPFB_INTERRUPT         0x8
>>>>> +#define INTELVIPFB_FRAME_COUNTER     0xC
>>>>> +#define INTELVIPFB_FRAME_DROP                0x10
>>>>> +#define INTELVIPFB_FRAME_INFO                0x14
>>>>> +#define INTELVIPFB_FRAME_START               0x18
>>>>> +#define INTELVIPFB_FRAME_READER              0x1C
>>>>> +
>>>>> +int intelvipfb_probe(struct device *dev, void __iomem *base); int
>>>>> +intelvipfb_remove(struct device *dev); int
>>>>> +intelvipfb_setup_crtc(struct drm_device *drm); int
>>>>> +intelvipfb_drm_conn_init(struct drm_device *drm);
>>>>> +
>>>>> +struct intelvipfb_priv {
>>>>> +     struct drm_fbdev_cma *fbcma;
>>>>> +     struct drm_device *drm;
>>>>> +     struct fb_info info;
>>>>> +     void    __iomem         *base;
>>>>> +};
>>>>> +
>>>>> +#endif
>>>>> diff --git a/drivers/gpu/drm/ivip/intel_vip_of.c
>>>>> b/drivers/gpu/drm/ivip/intel_vip_of.c
>>>>> new file mode 100644
>>>>> index 0000000..17dff36
>>>>> --- /dev/null
>>>>> +++ b/drivers/gpu/drm/ivip/intel_vip_of.c
>>>>> @@ -0,0 +1,146 @@
>>>>> +/*
>>>>> + * intel_vip_of.c -- Intel Video and Image Processing(VIP)
>>>>> + * Frame Buffer II driver
>>>>> + *
>>>>> + * This driver supports the Intel VIP Frame Reader component.
>>>>> + * More info on the hardware can be found in the Intel Video
>>>>> + * and Image Processing Suite User Guide at this address
>>>>> + * http://www.altera.com/literature/ug/ug_vip.pdf.
>>>>> + *
>>>>> + * 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.
>>>>> + *
>>>>> + * 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.
>>>>> + *
>>>>> + * Authors:
>>>>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>>>>> + *
>>>>> + */
>>>>> +
>>>>> +#include <linux/fb.h>
>>>>> +#include <linux/init.h>
>>>>> +#include <linux/kernel.h>
>>>>> +#include <linux/module.h>
>>>>> +#include <linux/platform_device.h>
>>>>> +
>>>>> +#include <drm/drm_fb_helper.h>
>>>>> +#include "intel_vip_drv.h"
>>>>> +
>>>>> +/*
>>>>> + * Setting up information derived from OF Device Tree Nodes
>>>>> + * max-width, max-height, bits per pixel, memory port width  */
>>>>> +
>>>>> +static int intelvipfb_of_setup(struct intelvipfb_priv *fbdata,
>>>>> +                            struct platform_device *pdev) {
>>>>> +     int ret;
>>>>> +     int mem_word_width;
>>>>> +     u32 bits_per_color;
>>>>> +     struct device_node *np = pdev->dev.of_node;
>>>>> +
>>>>> +     ret = of_property_read_u32(np, "altr,max-width",
>>>>> +                                &fbdata->info.var.xres);
>>>>> +     if (ret) {
>>>>> +             dev_err(&pdev->dev,
>>>>> +                     "Missing required parameter 'altr,max-
>>>>> width'");
>>>>> +             return ret;
>>>>> +     }
>>>>> +     fbdata->info.var.xres_virtual = fbdata->info.var.xres;
>>>>> +
>>>>> +     ret = of_property_read_u32(np, "altr,max-height",
>>>>> +                                &fbdata->info.var.yres);
>>>>> +     if (ret) {
>>>>> +             dev_err(&pdev->dev,
>>>>> +                     "Missing required parameter 'altr,max-
>>>>> height'");
>>>>> +             return ret;
>>>>> +     }
>>>>> +     fbdata->info.var.yres_virtual = fbdata->info.var.yres;
>>>>> +
>>>>> +     ret = of_property_read_u32(np, "altr,bits-per-symbol",
>>>>> &bits_per_color);
>>>>> +     if (ret) {
>>>>> +             dev_err(&pdev->dev,
>>>>> +                     "Missing required parameter 'altr,bits-per-
>>>>> symbol'");
>>>>> +             return ret;
>>>>> +     }
>>>>> +
>>>>> +     fbdata->info.var.bits_per_pixel = bits_per_color *
>>>>> BYTES_PER_PIXEL;
>>>>> +
>>>>> +     ret = of_property_read_u32(np, "altr,mem-port-width",
>>>>> &mem_word_width);
>>>>> +     if (ret) {
>>>>> +             dev_err(&pdev->dev,
>>>>> +                     "Missing required parameter 'altr,mem-port-
>>>>> width '");
>>>>> +             return ret;
>>>>> +     }
>>>>> +
>>>>> +     if (!(mem_word_width >= 32 && mem_word_width % 32 == 0)) {
>>>>> +             dev_err(&pdev->dev,
>>>>> +                     "mem-word-width is set to %i. must be >= 32
>>>>> and multiple of 32.",
>>>>> +                      mem_word_width);
>>>>> +             return -ENODEV;
>>>>> +     }
>>>>> +
>>>>> +     return 0;
>>>>> +}
>>>>> +
>>>>> +static int intelvipfb_of_probe(struct platform_device *pdev) {
>>>>> +     int retval;
>>>>> +     struct resource *reg_res;
>>>>> +     struct intelvipfb_priv *fbdata;
>>>>> +
>>>>> +     fbdata = devm_kzalloc(&pdev->dev, sizeof(*fbdata),
>>>>> GFP_KERNEL);
>>>>> +     if (!fbdata)
>>>>> +             return -ENOMEM;
>>>>> +
>>>>> +     reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>>> +     if (!reg_res)
>>>>> +             return -ENOMEM;
>>>>> +
>>>>> +     fbdata->base = devm_ioremap_resource(&pdev->dev, reg_res);
>>>>> +
>>>>> +     if (IS_ERR(fbdata->base)) {
>>>>> +             dev_err(&pdev->dev, "devm_ioremap_resource
>>>>> failed\n");
>>>>> +             retval = PTR_ERR(fbdata->base);
>>>>> +             return -ENOMEM;
>>>>> +     }
>>>>> +
>>>>> +     intelvipfb_of_setup(fbdata, pdev);
>>>>> +
>>>>> +     platform_set_drvdata(pdev, fbdata);
>>>>> +
>>>>> +     return intelvipfb_probe(&pdev->dev, fbdata->base); }
>>>>> +
>>>>> +static int intelvipfb_of_remove(struct platform_device *pdev) {
>>>>> +     return intelvipfb_remove(&pdev->dev); }
>>>>> +
>>>>> +/*
>>>>> + * The name vip-frame-buffer-2.0 is derived from
>>>>> + * http://www.altera.com/literature/ug/ug_vip.pdf
>>>>> + * frame buffer IP cores section 14  */
>>>>> +
>>>>> +static const struct of_device_id intelvipfb_of_match[] = {
>>>>> +     { .compatible = "altr,vip-frame-buffer-2.0" },
>>>>> +     {},
>>>>> +};
>>>>> +
>>>>> +MODULE_DEVICE_TABLE(of, intelvipfb_of_match);
>>>>> +
>>>>> +static struct platform_driver intelvipfb_driver = {
>>>>> +     .probe = intelvipfb_of_probe,
>>>>> +     .remove = intelvipfb_of_remove,
>>>>> +     .driver = {
>>>>> +             .name = DRIVER_NAME,
>>>>> +             .of_match_table = intelvipfb_of_match,
>>>>> +     },
>>>>> +};
>>>>> +
>>>>> +module_platform_driver(intelvipfb_driver);
>>>>> --
>>>>> 1.7.1
>>>>>
>>>>>
>>>>> -----Original Message-----
>>>>> From: Ong, Hean Loong
>>>>> Sent: Friday, March 31, 2017 5:09 PM
>>>>> To: Vetter, Daniel <daniel.vetter@intel.com>; airlied@linux.ie
>>>>> Cc: dri-devel@lists.freedesktop.org
>>>>> Subject: DRM Display driver for Intel FPGA Video and Image
>>>>> Processing Suite
>>>>>
>>>>> Hi,
>>>>>
>>>>> I would like to upstream the attached Intel FPGA Video and Image
>>>>> Processing Suite. The attached patch supports the Intel Arria10
>>>>> devkit and its variants. The purpose of the patch is to enable the
>>>>> FPGA driven display designed from the Intel Quartus FPGA design
>>>>> suite.
>>>>>
>>>>> The driver is required as part of the Intel Arria10 devkit
>>>>> reference design. The driver was tested on:
>>>>> - The Open Embedded Angstrom Distro.
>>>>> - The matchbox-terminal and window-manager was used for functional
>>>>> testing
>>>>>
>>>>> Current the intention of the driver is meant to validate the FPGA
>>>>> designs on the Arria10 devkit for Display Port connecter. We have
>>>>> not verified its performance of or stability in 3D acceleration or
>>>>> other non Intel FPGA hardware
>>>>>
>>>>> BR
>>>>>
>>>>> Hean Loong
>>>> _______________________________________________
>>>> dri-devel mailing list
>>>> dri-devel@lists.freedesktop.org
>>>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>>>
>>>
>>>
>>>--
>>>Daniel Vetter
>>>Software Engineer, Intel Corporation
>>>+41 (0) 79 365 57 48 - http://blog.ffwll.ch
>
>
>
>--
>Daniel Vetter
>Software Engineer, Intel Corporation
>+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: DRM Display driver for Intel FPGA Video and Image Processing Suite
  2017-04-10  7:49           ` Ong, Hean Loong
@ 2017-04-10  7:53             ` Daniel Vetter
  0 siblings, 0 replies; 9+ messages in thread
From: Daniel Vetter @ 2017-04-10  7:53 UTC (permalink / raw)
  To: Ong, Hean Loong; +Cc: Vetter, Daniel, dri-devel

On Mon, Apr 10, 2017 at 9:49 AM, Ong, Hean Loong
<hean.loong.ong@intel.com> wrote:
> Thanks again Daniel for the clarification.
>
> However I cannot seem to find the repo for the drm-misc and documentation on how to get it from the main kernel tree.
>
> Could you can give me some pointers on where to get the git tree of the drm-misc for small drivers. Sorry as I am not very familiar with the DRM architecture

The doc I linked also contains the git url:

https://01.org/linuxgraphics/gfx-docs/maintainer-tools/drm-misc.html

git://anongit.freedesktop.org/drm-misc

It is also listed in MAINTAINERS for each driver and subsystem
maintained in drm-misc.

Cheers, Daniel

>
>>-----Original Message-----
>>From: daniel.vetter@ffwll.ch [mailto:daniel.vetter@ffwll.ch] On Behalf Of Daniel
>>Vetter
>>Sent: Sunday, April 9, 2017 12:31 AM
>>To: Ong, Hean Loong <hean.loong.ong@intel.com>
>>Cc: Vetter, Daniel <daniel.vetter@intel.com>; airlied@linux.ie; dri-
>>devel@lists.freedesktop.org
>>Subject: Re: DRM Display driver for Intel FPGA Video and Image Processing Suite
>>
>>On Sat, Apr 8, 2017 at 7:41 AM, Ong, Hean Loong <hean.loong.ong@intel.com>
>>wrote:
>>> Hi Daniel
>>>
>>> Thanks for the time and patience for reviewing my changes. I would ensure that
>>subsequent patches will not have the same mail problems.
>>>
>>> I have some question on the validation methods. Since my drivers are
>>processing the images with an FPGA would running the tests with
>>https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#testing-and-validation
>>be relevant?
>>
>>igt testcases automatically skip when they don't apply for a given platform/driver.
>>They might need some bugfixes if your driver is a completely new case, but it
>>should work.
>>
>>> The display images are streamed to the monitor via a Display Port connector
>>thus I don' t think it is virtual. The FPGA is programmed to run with a proprietary
>>Display Port IP. The driver just feeds it with display data.
>>
>>Well, it looked like a virtual driver (since the real DP handling is somewhere else
>>like you explain). And since it works like a virtual driver we could extract a helper
>>library to reduce duplicated code.
>>Virtual driver here means "just feeds display data to something else that handles
>>the real output handling duties". That applies to virtualized gpus, but also to your
>>case here.
>>
>>Btw a small ascii-art block diagram for your driver hw architecture to explain stuff
>>like this would be awesome (but it either into a code comment or into the commit
>>message).
>>
>>> I would take your advice in implementing it in the small drivers, but since its new
>>are there any special cases that I would have to look out for in implementing this
>>driver in the drm-misc ?
>>
>>Small drivers is only about how to maintain it once it's merged, not about the
>>code itself. We assume/hope that people who submit drivers stay around for
>>helping maintaining it going forward (but if that doesn't happen, also no big deal).
>>-Daniel
>>
>>>
>>>>-----Original Message-----
>>>>From: daniel.vetter@ffwll.ch [mailto:daniel.vetter@ffwll.ch] On Behalf
>>>>Of Daniel Vetter
>>>>Sent: Saturday, April 8, 2017 12:32 AM
>>>>To: Ong, Hean Loong <hean.loong.ong@intel.com>
>>>>Cc: Vetter, Daniel <daniel.vetter@intel.com>; airlied@linux.ie; dri-
>>>>devel@lists.freedesktop.org
>>>>Subject: Re: DRM Display driver for Intel FPGA Video and Image
>>>>Processing Suite
>>>>
>>>>On Thu, Apr 6, 2017 at 8:29 AM, Ong, Hean Loong
>>>><hean.loong.ong@intel.com>
>>>>wrote:
>>>>> Hi All,
>>>>>
>>>>> Any comments for the patch below?
>>>>
>>>>Seems the same version that I already reviewed. My comment about not
>>>>sending inline was more for the next version, especially once it's
>>>>about applying the patch, attached patches are a bit of a pain (since they break
>>the tooling here).
>>>>-Daniel
>>>>>
>>>>> Thanks
>>>>>
>>>>> Hean Loong
>>>>>
>>>>> On Tue, 2017-04-04 at 04:01 +0000, Ong, Hean Loong wrote:
>>>>>> Hi All,
>>>>>>
>>>>>> Apologies for the attachment earlier. Below are the inline changes
>>>>>> for the patch
>>>>>>
>>>>>> From 0de293e3646a1780ed603cf8e1f2a19d9aebbe83 Mon Sep 17 00:00:00
>>>>>> 2001
>>>>>> From: Ong, Hean Loong <hean.loong.ong@intel.com>
>>>>>> Date: Thu, 30 Mar 2017 18:02:22 +0800
>>>>>> Subject: [PATCHv0] Intel FPGA Video and Image Processing Suite
>>>>>> Frame Buffer II driver
>>>>>>
>>>>>> Signed-off-by: Ong, Hean Loong <hean.loong.ong@intel.com>
>>>>>> ---
>>>>>>  drivers/gpu/drm/Kconfig               |    2 +
>>>>>>  drivers/gpu/drm/Makefile              |    1 +
>>>>>>  drivers/gpu/drm/ivip/Kconfig          |   22 ++++
>>>>>>  drivers/gpu/drm/ivip/Makefile         |    9 ++
>>>>>>  drivers/gpu/drm/ivip/intel_vip_conn.c |  145
>>>>>> ++++++++++++++++++++++ drivers/gpu/drm/ivip/intel_vip_core.c |  215
>>>>>> +++++++++++++++++++++++++++++++++
>>>>>>  drivers/gpu/drm/ivip/intel_vip_crtc.c |  161
>>>>>> ++++++++++++++++++++++++
>>>>>>  drivers/gpu/drm/ivip/intel_vip_drv.h  |   55 +++++++++
>>>>>>  drivers/gpu/drm/ivip/intel_vip_of.c   |  146 ++++++++++++++++++++++
>>>>>>  9 files changed, 756 insertions(+), 0 deletions(-)  create mode
>>>>>> 100644 drivers/gpu/drm/ivip/Kconfig  create mode 100644
>>>>>> drivers/gpu/drm/ivip/Makefile  create mode 100644
>>>>>> drivers/gpu/drm/ivip/intel_vip_conn.c
>>>>>>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_core.c
>>>>>>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_crtc.c
>>>>>>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_drv.h
>>>>>>  create mode 100644 drivers/gpu/drm/ivip/intel_vip_of.c
>>>>>>
>>>>>> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
>>>>>> index
>>>>>> ebfe840..c487507 100644
>>>>>> --- a/drivers/gpu/drm/Kconfig
>>>>>> +++ b/drivers/gpu/drm/Kconfig
>>>>>> @@ -167,6 +167,8 @@ source "drivers/gpu/drm/nouveau/Kconfig"
>>>>>>
>>>>>>  source "drivers/gpu/drm/i915/Kconfig"
>>>>>>
>>>>>> +source "drivers/gpu/drm/ivip/Kconfig"
>>>>>> +
>>>>>>  config DRM_VGEM
>>>>>>       tristate "Virtual GEM provider"
>>>>>>       depends on DRM
>>>>>> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
>>>>>> index b9ae428..945cf53 100644
>>>>>> --- a/drivers/gpu/drm/Makefile
>>>>>> +++ b/drivers/gpu/drm/Makefile
>>>>>> @@ -52,6 +52,7 @@ obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/
>>>>>>  obj-$(CONFIG_DRM_MGA)        += mga/
>>>>>>  obj-$(CONFIG_DRM_I810)       += i810/
>>>>>>  obj-$(CONFIG_DRM_I915)       += i915/
>>>>>> +obj-$(CONFIG_DRM_IVIP)       += ivip/
>>>>>>  obj-$(CONFIG_DRM_MGAG200) += mgag200/
>>>>>>  obj-$(CONFIG_DRM_VC4)  += vc4/
>>>>>>  obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus/ diff --git
>>>>>> a/drivers/gpu/drm/ivip/Kconfig b/drivers/gpu/drm/ivip/Kconfig new
>>>>>> file mode 100644 index 0000000..ddf3cb5
>>>>>> --- /dev/null
>>>>>> +++ b/drivers/gpu/drm/ivip/Kconfig
>>>>>> @@ -0,0 +1,22 @@
>>>>>> +config DRM_IVIP
>>>>>> +        tristate "Intel FGPA Video and Image Processing"
>>>>>> +        depends on DRM
>>>>>> +        select DRM_GEM_CMA_HELPER
>>>>>> +        select DRM_KMS_HELPER
>>>>>> +        select DRM_KMS_FB_HELPER
>>>>>> +        select DRM_KMS_CMA_HELPER
>>>>>> +        help
>>>>>> +                Choose this option if you have a Intel FPGA Arria
>>>>>> +10
>>>>>> system
>>>>>> +                and above with a Display Port IP. This does not
>>>>>> support legacy
>>>>>> +                Intel FPGA Cyclone V display port. Currently only
>>>>>> single frame
>>>>>> +                buffer is supported. Note that ACPI and X_86
>>>>>> architecture is yet
>>>>>> +                to be supported.
>>>>>> +
>>>>>> +config DRM_IVIP_OF
>>>>>> +        tristate "Intel FGPA Video and Image Processing Open
>>>>>> Firmware Systems"
>>>>>> +        depends on DRM_IVIP && OF
>>>>>> +        help
>>>>>> +                Choose this option if the Intel FPGA system is
>>>>>> + using
>>>>>> Open
>>>>>> +                Firmware systems (Arria 10). If M is selected the
>>>>>> module would
>>>>>> +                be called ivip.
>>>>>> +
>>>>>> diff --git a/drivers/gpu/drm/ivip/Makefile
>>>>>> b/drivers/gpu/drm/ivip/Makefile new file mode 100644 index
>>>>>> 0000000..7be1e99
>>>>>> --- /dev/null
>>>>>> +++ b/drivers/gpu/drm/ivip/Makefile
>>>>>> @@ -0,0 +1,9 @@
>>>>>> +#
>>>>>> +# Makefile for the drm device driver.  This driver provides
>>>>>> +support
>>>>>> for the
>>>>>> +# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
>>>>>> +
>>>>>> +ccflags-y := -Iinclude/drm
>>>>>> +
>>>>>> +obj-$(CONFIG_DRM_IVIP_OF) += ivip.o ivip-objs := intel_vip_of.o
>>>>>> +intel_vip_core.o \ intel_vip_conn.o intel_vip_crtc.o
>>>>>> diff --git a/drivers/gpu/drm/ivip/intel_vip_conn.c
>>>>>> b/drivers/gpu/drm/ivip/intel_vip_conn.c
>>>>>> new file mode 100644
>>>>>> index 0000000..89ab587
>>>>>> --- /dev/null
>>>>>> +++ b/drivers/gpu/drm/ivip/intel_vip_conn.c
>>>>>> @@ -0,0 +1,145 @@
>>>>>> +/*
>>>>>> + * intel_vip_conn.c -- Intel Video and Image Processing(VIP)
>>>>>> + * Frame Buffer II driver
>>>>>> + *
>>>>>> + * This driver supports the Intel VIP Frame Reader component.
>>>>>> + * More info on the hardware can be found in the Intel Video
>>>>>> + * and Image Processing Suite User Guide at this address
>>>>>> + * http://www.altera.com/literature/ug/ug_vip.pdf.
>>>>>> + *
>>>>>> + * 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.
>>>>>> + *
>>>>>> + * 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.
>>>>>> + *
>>>>>> + * Authors:
>>>>>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>>>>>> + *
>>>>>> + */
>>>>>> +
>>>>>> +#include <linux/init.h>
>>>>>> +#include <linux/kernel.h>
>>>>>> +#include <drm/drm_atomic_helper.h> #include
>>>>>> +<drm/drm_crtc_helper.h> #include <drm/drm_encoder_slave.h>
>>>>>> +#include <drm/drm_plane_helper.h>
>>>>>> +
>>>>>> +static enum drm_connector_status
>>>>>> +intelvipfb_drm_connector_detect(struct drm_connector *connector,
>>>>>> bool force)
>>>>>> +{
>>>>>> +     return connector_status_connected; }
>>>>>> +
>>>>>> +static void intelvipfb_drm_connector_destroy(struct drm_connector
>>>>>> *connector)
>>>>>> +{
>>>>>> +     drm_connector_unregister(connector);
>>>>>> +     drm_connector_cleanup(connector); }
>>>>>> +
>>>>>> +static const struct drm_connector_funcs
>>>>>> intelvipfb_drm_connector_funcs = {
>>>>>> +     .dpms = drm_helper_connector_dpms,
>>>>>> +     .reset = drm_atomic_helper_connector_reset,
>>>>>> +     .detect = intelvipfb_drm_connector_detect,
>>>>>> +     .fill_modes = drm_helper_probe_single_connector_modes,
>>>>>> +     .destroy = intelvipfb_drm_connector_destroy,
>>>>>> +     .atomic_duplicate_state =
>>>>>> drm_atomic_helper_connector_duplicate_state,
>>>>>> +     .atomic_destroy_state =
>>>>>> drm_atomic_helper_connector_destroy_state,
>>>>>> +};
>>>>>> +
>>>>>> +static int intelvipfb_drm_connector_get_modes(struct drm_connector
>>>>>> *connector)
>>>>>> +{
>>>>>> +     struct drm_device *drm = connector->dev;
>>>>>> +     int count;
>>>>>> +
>>>>>> +     count = drm_add_modes_noedid(connector, drm-
>>>>>> >mode_config.max_width,
>>>>>> +                                  drm->mode_config.max_height);
>>>>>> +     drm_set_preferred_mode(connector, drm-
>>>>>> >mode_config.max_width,
>>>>>> +                            drm->mode_config.max_height);
>>>>>> +     return count;
>>>>>> +}
>>>>>> +
>>>>>> +static const struct drm_connector_helper_funcs
>>>>>> +intelvipfb_drm_connector_helper_funcs = {
>>>>>> +     .get_modes = intelvipfb_drm_connector_get_modes,
>>>>>> +};
>>>>>> +
>>>>>> +static const struct drm_encoder_funcs intelvipfb_drm_encoder_funcs
>>>>>> += {
>>>>>> +     .destroy = drm_encoder_cleanup, };
>>>>>> +
>>>>>> +static void intelvipfb_mode_set(struct drm_encoder *encoder,
>>>>>> +                             struct drm_display_mode *mode,
>>>>>> +                             struct drm_display_mode
>>>>>> *adjusted_mode)
>>>>>> +{
>>>>>> +     /* do nothing */
>>>>>> +}
>>>>>> +
>>>>>> +static void intelvipfb_nop(struct drm_encoder *encoder) {
>>>>>> +     /* do nothing */
>>>>>> +}
>>>>>> +
>>>>>> +static const struct drm_encoder_helper_funcs i
>>>>>> +intelvipfb_drm_encoder_helper = {
>>>>>> +     .mode_set = intelvipfb_mode_set,
>>>>>> +     .enable = intelvipfb_nop,
>>>>>> +     .disable = intelvipfb_nop,
>>>>>> +};
>>>>>> +
>>>>>> +int intelvipfb_drm_conn_init(struct drm_device *drm) {
>>>>>> +     struct drm_encoder_slave *encoder;
>>>>>> +     struct drm_connector *conn;
>>>>>> +     int ret;
>>>>>> +
>>>>>> +     encoder = devm_kzalloc(drm->dev, sizeof(*encoder),
>>>>>> GFP_KERNEL);
>>>>>> +     if (!encoder)
>>>>>> +             return -ENOMEM;
>>>>>> +
>>>>>> +     encoder->base.possible_crtcs = 1;
>>>>>> +     encoder->base.possible_clones = 0;
>>>>>> +
>>>>>> +     ret = drm_encoder_init(drm, &encoder->base,
>>>>>> +                            &intelvipfb_drm_encoder_funcs,
>>>>>> +                            DRM_MODE_ENCODER_VIRTUAL, NULL);
>>>>>> +     if (ret)
>>>>>> +             return ret;
>>>>>> +
>>>>>> +     drm_encoder_helper_add(&encoder->base,
>>>>>> &intelvipfb_drm_encoder_helper);
>>>>>> +
>>>>>> +     conn = devm_kzalloc(drm->dev, sizeof(*conn), GFP_KERNEL);
>>>>>> +     if (IS_ERR(conn))
>>>>>> +             return PTR_ERR(conn);
>>>>>> +
>>>>>> +     ret = drm_connector_init(drm, conn,
>>>>>> &intelvipfb_drm_connector_funcs,
>>>>>> +                              DRM_MODE_CONNECTOR_DisplayPort);
>>>>>> +     if (ret < 0) {
>>>>>> +             dev_err(drm->dev, "failed to initialize drm
>>>>>> connector\n");
>>>>>> +             ret = -ENOMEM;
>>>>>> +             goto error_encoder_cleanup;
>>>>>> +     }
>>>>>> +
>>>>>> +     drm_connector_helper_add(conn,
>>>>>> &intelvipfb_drm_connector_helper_funcs);
>>>>>> +
>>>>>> +     ret = drm_mode_connector_attach_encoder(conn, &encoder-
>>>>>> >base);
>>>>>> +     if (ret < 0) {
>>>>>> +             dev_err(drm->dev, "could not attach connector to
>>>>>> encoder\n");
>>>>>> +             drm_connector_unregister(conn);
>>>>>> +             goto error_connector_cleanup;
>>>>>> +     }
>>>>>> +
>>>>>> +     return 0;
>>>>>> +
>>>>>> +error_connector_cleanup:
>>>>>> +     drm_connector_cleanup(conn);
>>>>>> +
>>>>>> +error_encoder_cleanup:
>>>>>> +     drm_encoder_cleanup(&encoder->base);
>>>>>> +
>>>>>> +     return ret;
>>>>>> +}
>>>>>> diff --git a/drivers/gpu/drm/ivip/intel_vip_core.c
>>>>>> b/drivers/gpu/drm/ivip/intel_vip_core.c
>>>>>> new file mode 100644
>>>>>> index 0000000..3001ad0
>>>>>> --- /dev/null
>>>>>> +++ b/drivers/gpu/drm/ivip/intel_vip_core.c
>>>>>> @@ -0,0 +1,215 @@
>>>>>> +/*
>>>>>> + * intel_vip_core.c -- Intel Video and Image Processing(VIP)
>>>>>> + * Frame Buffer II driver
>>>>>> + *
>>>>>> + * This driver supports the Intel VIP Frame Reader component.
>>>>>> + * More info on the hardware can be found in the Intel Video
>>>>>> + * and Image Processing Suite User Guide at this address
>>>>>> + * http://www.altera.com/literature/ug/ug_vip.pdf.
>>>>>> + *
>>>>>> + * 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.
>>>>>> + *
>>>>>> + * 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.
>>>>>> + *
>>>>>> + * Authors:
>>>>>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>>>>>> + *
>>>>>> + */
>>>>>> +
>>>>>> +#include <linux/init.h>
>>>>>> +#include <linux/kernel.h>
>>>>>> +#include <linux/module.h>
>>>>>> +
>>>>>> +#include <drm/drmP.h>
>>>>>> +#include <drm/drm_atomic.h>
>>>>>> +#include <drm/drm_atomic_helper.h> #include
>>>>>> +<drm/drm_crtc_helper.h> #include <drm/drm_fb_helper.h> #include
>>>>>> +<drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
>>>>>> +#include <drm/drm_of.h>
>>>>>> +
>>>>>> +#include "intel_vip_drv.h"
>>>>>> +
>>>>>> +static const struct file_operations intelvipfb_drm_fops = {
>>>>>> +     .owner          = THIS_MODULE,
>>>>>> +     .open           = drm_open,
>>>>>> +     .release        = drm_release,
>>>>>> +     .unlocked_ioctl = drm_ioctl,
>>>>>> +     .poll           = drm_poll,
>>>>>> +     .read           = drm_read,
>>>>>> +     .llseek         = no_llseek,
>>>>>> +     .mmap           = drm_gem_cma_mmap,
>>>>>> +};
>>>>>> +
>>>>>> +static void intelvipfb_lastclose(struct drm_device *drm) {
>>>>>> +     struct intelvipfb_priv *fbpriv = drm->dev_private;
>>>>>> +
>>>>>> +     drm_fbdev_cma_restore_mode(fbpriv->fbcma);
>>>>>> +}
>>>>>> +
>>>>>> +static struct drm_driver intelvipfb_drm = {
>>>>>> +     .driver_features =
>>>>>> +         DRIVER_GEM | DRIVER_PRIME |
>>>>>> +         DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC,
>>>>>> +     .gem_free_object_unlocked = drm_gem_cma_free_object,
>>>>>> +     .gem_vm_ops = &drm_gem_cma_vm_ops,
>>>>>> +     .dumb_create = drm_gem_cma_dumb_create,
>>>>>> +     .dumb_map_offset = drm_gem_cma_dumb_map_offset,
>>>>>> +     .dumb_destroy = drm_gem_dumb_destroy,
>>>>>> +     .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
>>>>>> +     .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
>>>>>> +     .gem_prime_export = drm_gem_prime_export,
>>>>>> +     .gem_prime_import = drm_gem_prime_import,
>>>>>> +     .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
>>>>>> +     .gem_prime_import_sg_table =
>>>>>> drm_gem_cma_prime_import_sg_table,
>>>>>> +     .gem_prime_vmap = drm_gem_cma_prime_vmap,
>>>>>> +     .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
>>>>>> +     .gem_prime_mmap = drm_gem_cma_prime_mmap,
>>>>>> +     .name = DRIVER_NAME,
>>>>>> +     .date = "20170329",
>>>>>> +     .desc = "Intel FPGA VIP SUITE",
>>>>>> +     .major = 1,
>>>>>> +     .minor = 0,
>>>>>> +     .patchlevel = 0,
>>>>>> +     .lastclose = intelvipfb_lastclose,
>>>>>> +     .fops = &intelvipfb_drm_fops, };
>>>>>> +
>>>>>> +static void intelvipfb_start_hw(void __iomem *base,
>>>>>> +resource_size_t
>>>>>> addr)
>>>>>> +{
>>>>>> +     /*
>>>>>> +      * The frameinfo variable has to correspond to the size of
>>>>>> the VIP Suite
>>>>>> +      * Frame Reader register 7 which will determine the maximum
>>>>>> size used
>>>>>> +      * in this frameinfo
>>>>>> +      */
>>>>>> +
>>>>>> +     u32 frameinfo;
>>>>>> +
>>>>>> +     frameinfo =
>>>>>> +             readl(base + INTELVIPFB_FRAME_READER) & 0x00ffffff;
>>>>>> +
>>>>>> +     writel(frameinfo, base + INTELVIPFB_FRAME_INFO);
>>>>>> +
>>>>>> +     writel(addr, base + INTELVIPFB_FRAME_START);
>>>>>> +     /* Finally set the control register to 1 to start streaming
>>>>>> */
>>>>>> +     writel(1, base + INTELVIPFB_CONTROL); }
>>>>>> +
>>>>>> +static void intelvipfb_disable_hw(void __iomem *base) {
>>>>>> +     /* set the control register to 0 to stop streaming */
>>>>>> +     writel(0, base + INTELVIPFB_CONTROL); }
>>>>>> +
>>>>>> +static void intelvipfb_output_poll_changed(struct drm_device *drm) {
>>>>>> +     struct intelvipfb_priv *fbpriv = drm->dev_private;
>>>>>> +
>>>>>> +     drm_fbdev_cma_hotplug_event(fbpriv->fbcma);
>>>>>> +}
>>>>>> +
>>>>>> +static const struct drm_mode_config_funcs
>>>>>> intelvipfb_mode_config_funcs = {
>>>>>> +     .fb_create = drm_fb_cma_create,
>>>>>> +     .output_poll_changed = intelvipfb_output_poll_changed,
>>>>>> +     .atomic_check = drm_atomic_helper_check,
>>>>>> +     .atomic_commit = drm_atomic_helper_commit, };
>>>>>> +
>>>>>> +static struct drm_mode_config_helper_funcs
>>>>>> intelvipfb_mode_config_helpers = {
>>>>>> +     .atomic_commit_tail = drm_atomic_helper_commit_tail, };
>>>>>> +
>>>>>> +static void intelvipfb_setup_mode_config(struct drm_device *drm,
>>>>>> +                                      struct fb_info *info) {
>>>>>> +     drm_mode_config_init(drm);
>>>>>> +     drm->mode_config.min_width = 0;
>>>>>> +     drm->mode_config.min_height = 0;
>>>>>> +     drm->mode_config.max_width = info->var.xres;
>>>>>> +     drm->mode_config.max_height = info->var.yres;
>>>>>> +     drm->mode_config.preferred_depth = 32;
>>>>>> +     drm->mode_config.funcs = &intelvipfb_mode_config_funcs;
>>>>>> +     drm->mode_config.helper_private =
>>>>>> &intelvipfb_mode_config_helpers;
>>>>>> +}
>>>>>> +
>>>>>> +int intelvipfb_probe(struct device *dev, void __iomem *base) {
>>>>>> +     int retval;
>>>>>> +     struct drm_device *drm;
>>>>>> +     struct intelvipfb_priv *fbpriv = dev_get_drvdata(dev);
>>>>>> +     struct fb_info *info = &fbpriv->info;
>>>>>> +
>>>>>> +     /*setup DRM */
>>>>>> +     drm = drm_dev_alloc(&intelvipfb_drm, dev);
>>>>>> +     if (IS_ERR(drm))
>>>>>> +             return PTR_ERR(drm);
>>>>>> +
>>>>>> +     drm->dev_private = fbpriv;
>>>>>> +
>>>>>> +     dev_set_drvdata(dev, drm);
>>>>>> +
>>>>>> +     intelvipfb_setup_mode_config(drm, info);
>>>>>> +
>>>>>> +     retval = dma_set_mask_and_coherent(drm->dev,
>>>>>> DMA_BIT_MASK(32));
>>>>>> +     if (retval)
>>>>>> +             return -ENODEV;
>>>>>> +
>>>>>> +     retval = intelvipfb_setup_crtc(drm);
>>>>>> +     if (retval < 0)
>>>>>> +             return -ENODEV;
>>>>>> +
>>>>>> +     retval = intelvipfb_drm_conn_init(drm);
>>>>>> +     if (retval)
>>>>>> +             return -ENOMEM;
>>>>>> +
>>>>>> +     drm_mode_config_reset(drm);
>>>>>> +
>>>>>> +     fbpriv->fbcma = drm_fbdev_cma_init(drm, PREF_BPP,
>>>>>> +                                                     CRTC_NUM,
>>>>>> CONN_NUM);
>>>>>> +     if (!fbpriv->fbcma) {
>>>>>> +             fbpriv->fbcma = NULL;
>>>>>> +             return -ENODEV;
>>>>>> +     }
>>>>>> +
>>>>>> +     intelvipfb_start_hw(base, drm->mode_config.fb_base);
>>>>>> +
>>>>>> +     drm_kms_helper_poll_init(drm);
>>>>>> +
>>>>>> +     drm_dev_register(drm, 0);
>>>>>> +
>>>>>> +     return retval;
>>>>>> +}
>>>>>> +EXPORT_SYMBOL_GPL(intelvipfb_probe);
>>>>>> +
>>>>>> +int intelvipfb_remove(struct device *dev) {
>>>>>> +     struct drm_device *drm = dev_get_drvdata(dev);
>>>>>> +     struct intelvipfb_priv *fbpriv = drm->dev_private;
>>>>>> +
>>>>>> +     drm_dev_unregister(drm);
>>>>>> +
>>>>>> +     drm_kms_helper_poll_fini(drm);
>>>>>> +     drm_fbdev_cma_fini(fbpriv->fbcma);
>>>>>> +
>>>>>> +     intelvipfb_disable_hw(fbpriv->base);
>>>>>> +
>>>>>> +drm_mode_config_cleanup(drm);
>>>>>> +
>>>>>> +drm_dev_unref(drm);
>>>>>> +
>>>>>> +devm_kfree(dev, fbpriv);
>>>>>> +
>>>>>> +     return 0;
>>>>>> +}
>>>>>> +EXPORT_SYMBOL_GPL(intelvipfb_remove);
>>>>>> +
>>>>>> +MODULE_AUTHOR("Ong, Hean-Loong <hean.loong.ong@intel.com>");
>>>>>> +MODULE_DESCRIPTION("Intel VIP Frame Buffer II driver");
>>>>>> +MODULE_LICENSE("GPL v2");
>>>>>> diff --git a/drivers/gpu/drm/ivip/intel_vip_crtc.c
>>>>>> b/drivers/gpu/drm/ivip/intel_vip_crtc.c
>>>>>> new file mode 100644
>>>>>> index 0000000..97a3954
>>>>>> --- /dev/null
>>>>>> +++ b/drivers/gpu/drm/ivip/intel_vip_crtc.c
>>>>>> @@ -0,0 +1,161 @@
>>>>>> +/*
>>>>>> + * intel_vip_crtc.c -- Intel Video and Image Processing(VIP)
>>>>>> + * Frame Buffer II driver
>>>>>> + *
>>>>>> + * This driver supports the Intel VIP Frame Reader component.
>>>>>> + * More info on the hardware can be found in the Intel Video
>>>>>> + * and Image Processing Suite User Guide at this address
>>>>>> + * http://www.altera.com/literature/ug/ug_vip.pdf.
>>>>>> + *
>>>>>> + * 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.
>>>>>> + *
>>>>>> + * 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.
>>>>>> + *
>>>>>> + * Authors:
>>>>>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>>>>>> + *
>>>>>> + */
>>>>>> +
>>>>>> +#include <linux/init.h>
>>>>>> +#include <linux/kernel.h>
>>>>>> +#include <linux/platform_data/simplefb.h>
>>>>>> +
>>>>>> +#include <drm/drm_atomic.h>
>>>>>> +#include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h>
>>>>>> +#include <drm/drm_crtc_helper.h> #include
>>>>>> +<drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
>>>>>> +#include <drm/drm_plane_helper.h>
>>>>>> +
>>>>>> +#include "intel_vip_drv.h"
>>>>>> +
>>>>>> +static struct simplefb_format intelvipfb_formats[] =
>>>>>> SIMPLEFB_FORMATS;
>>>>>> +
>>>>>> +static void intelvipfb_crtc_destroy(struct drm_crtc *crtc) {
>>>>>> +     drm_crtc_cleanup(crtc);
>>>>>> +     kfree(crtc);
>>>>>> +}
>>>>>> +
>>>>>> +static const struct drm_crtc_funcs intelvipfb_crtc_funcs = {
>>>>>> +     .destroy = intelvipfb_crtc_destroy,
>>>>>> +     .set_config = drm_atomic_helper_set_config,
>>>>>> +     .page_flip = drm_atomic_helper_page_flip,
>>>>>> +     .reset = drm_atomic_helper_crtc_reset,
>>>>>> +     .atomic_duplicate_state =
>>>>>> drm_atomic_helper_crtc_duplicate_state,
>>>>>> +     .atomic_destroy_state =
>>>>>> drm_atomic_helper_crtc_destroy_state,
>>>>>> +};
>>>>>> +
>>>>>> +static void intelvipfb_crtc_atomic_begin(struct drm_crtc *crtc,
>>>>>> +                                      struct drm_crtc_state
>>>>>> *state)
>>>>>> +{
>>>>>> +     struct drm_pending_vblank_event *event = crtc->state->event;
>>>>>> +
>>>>>> +     if (event) {
>>>>>> +             crtc->state->event = NULL;
>>>>>> +
>>>>>> +             spin_lock_irq(&crtc->dev->event_lock);
>>>>>> +             drm_crtc_send_vblank_event(crtc, event);
>>>>>> +             spin_unlock_irq(&crtc->dev->event_lock);
>>>>>> +     }
>>>>>> +}
>>>>>> +
>>>>>> +static void intelvipfb_crtc_nop(struct drm_crtc *crtc) {
>>>>>> +     /* do nothing */;
>>>>>> +}
>>>>>> +
>>>>>> +static const struct drm_crtc_helper_funcs
>>>>>> intelvipfb_crtc_helper_funcs = {
>>>>>> +     .atomic_begin   = intelvipfb_crtc_atomic_begin,
>>>>>> +     .enable = intelvipfb_crtc_nop, };
>>>>>> +
>>>>>> +static void intelvipfb_plane_destroy(struct drm_plane *plane) {
>>>>>> +     drm_plane_helper_disable(plane);
>>>>>> +     drm_plane_cleanup(plane);
>>>>>> +}
>>>>>> +
>>>>>> +static const struct drm_plane_funcs intelvipfb_plane_funcs = {
>>>>>> +     .update_plane           =
>>>>>> drm_atomic_helper_update_plane,
>>>>>> +     .disable_plane          =
>>>>>> drm_atomic_helper_disable_plane,
>>>>>> +     .destroy                = intelvipfb_plane_destroy,
>>>>>> +     .reset                  =
>>>>>> drm_atomic_helper_plane_reset,
>>>>>> +     .atomic_duplicate_state =
>>>>>> drm_atomic_helper_plane_duplicate_state,
>>>>>> +     .atomic_destroy_state   =
>>>>>> drm_atomic_helper_plane_destroy_state,
>>>>>> +};
>>>>>> +
>>>>>> +static void intelvipfb_plane_atomic_update(struct drm_plane *plane,
>>>>>> +                                        struct drm_plane_state
>>>>>> *state)
>>>>>> +{
>>>>>> +     struct intelvipfb_priv *fbpriv;
>>>>>> +     struct drm_gem_cma_object *gem;
>>>>>> +
>>>>>> +     if (!plane->state->crtc || !plane->state->fb)
>>>>>> +             return;
>>>>>> +
>>>>>> +     fbpriv = plane->dev->dev_private;
>>>>>> +     gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
>>>>>> +     writel(gem->paddr, fbpriv->base + INTELVIPFB_FRAME_START); }
>>>>>> +
>>>>>> +static const struct drm_plane_helper_funcs
>>>>>> intelvipfb_plane_helper_funcs = {
>>>>>> +     .atomic_update = intelvipfb_plane_atomic_update, };
>>>>>> +
>>>>>> +static struct drm_plane *intelvipfb_plane_init(struct drm_device
>>>>>> *drm)
>>>>>> +{
>>>>>> +     struct drm_plane *plane = NULL;
>>>>>> +     u32 formats[ARRAY_SIZE(intelvipfb_formats)], i;
>>>>>> +     int ret;
>>>>>> +
>>>>>> +     plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
>>>>>> +     if (!plane)
>>>>>> +             return ERR_PTR(-ENOMEM);
>>>>>> +
>>>>>> +     for (i = 0; i < ARRAY_SIZE(intelvipfb_formats); i++)
>>>>>> +             formats[i] = intelvipfb_formats[i].fourcc;
>>>>>> +
>>>>>> +     ret = drm_universal_plane_init(drm, plane, 0xff,
>>>>>> +                                    &intelvipfb_plane_funcs,
>>>>>> +                                    formats, ARRAY_SIZE(formats),
>>>>>> +                                    DRM_PLANE_TYPE_PRIMARY,
>>>>>> NULL);
>>>>>> +     if (ret)
>>>>>> +             return ERR_PTR(ret);
>>>>>> +
>>>>>> +     drm_plane_helper_add(plane, &intelvipfb_plane_helper_funcs);
>>>>>> +
>>>>>> +     return plane;
>>>>>> +}
>>>>>> +
>>>>>> +int intelvipfb_setup_crtc(struct drm_device *drm) {
>>>>>> +     struct drm_crtc *crtc;
>>>>>> +     struct drm_plane *primary;
>>>>>> +     int ret;
>>>>>> +
>>>>>> +     crtc = kzalloc(sizeof(*crtc), GFP_KERNEL);
>>>>>> +     if (!crtc)
>>>>>> +             return -ENOMEM;
>>>>>> +
>>>>>> +     primary = intelvipfb_plane_init(drm);
>>>>>> +     if (IS_ERR(primary))
>>>>>> +             return PTR_ERR(primary);
>>>>>> +
>>>>>> +     ret = drm_crtc_init_with_planes(drm, crtc, primary, NULL,
>>>>>> +                                     &intelvipfb_crtc_funcs,
>>>>>> NULL);
>>>>>> +
>>>>>> +     if (ret) {
>>>>>> +             intelvipfb_plane_destroy(primary);
>>>>>> +             return ret;
>>>>>> +     }
>>>>>> +
>>>>>> +     drm_crtc_helper_add(crtc, &intelvipfb_crtc_helper_funcs);
>>>>>> +     return 0;
>>>>>> +}
>>>>>> diff --git a/drivers/gpu/drm/ivip/intel_vip_drv.h
>>>>>> b/drivers/gpu/drm/ivip/intel_vip_drv.h
>>>>>> new file mode 100644
>>>>>> index 0000000..657f23c
>>>>>> --- /dev/null
>>>>>> +++ b/drivers/gpu/drm/ivip/intel_vip_drv.h
>>>>>> @@ -0,0 +1,55 @@
>>>>>> +/*
>>>>>> + * Copyright (C) 2017 Intel Corporation.
>>>>>> + *
>>>>>> + * Intel Video and Image Processing(VIP) Frame Buffer II driver.
>>>>>> + *
>>>>>> + * 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.
>>>>>> + *
>>>>>> + * 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.
>>>>>> + *
>>>>>> + * You should have received a copy of the GNU General Public
>>>>>> + License
>>>>>> along with
>>>>>> + * this program.  If not, see <http://www.gnu.org/licenses/>.
>>>>>> + *
>>>>>> + * Authors:
>>>>>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>>>>>> + *
>>>>>> + */
>>>>>> +#ifndef _INTEL_VIP_DRV_H
>>>>>> +#define _INTEL_VIP_DRV_H
>>>>>> +#include <linux/io.h>
>>>>>> +#include <linux/fb.h>
>>>>>> +
>>>>>> +#define DRIVER_NAME  "intelvipfb"
>>>>>> +#define BYTES_PER_PIXEL      4
>>>>>> +#define PREF_BPP             32
>>>>>> +#define CRTC_NUM             1
>>>>>> +#define CONN_NUM             1
>>>>>> +
>>>>>> +/* control registers */
>>>>>> +#define INTELVIPFB_CONTROL           0
>>>>>> +#define INTELVIPFB_STATUS            0x4
>>>>>> +#define INTELVIPFB_INTERRUPT         0x8
>>>>>> +#define INTELVIPFB_FRAME_COUNTER     0xC
>>>>>> +#define INTELVIPFB_FRAME_DROP                0x10
>>>>>> +#define INTELVIPFB_FRAME_INFO                0x14
>>>>>> +#define INTELVIPFB_FRAME_START               0x18
>>>>>> +#define INTELVIPFB_FRAME_READER              0x1C
>>>>>> +
>>>>>> +int intelvipfb_probe(struct device *dev, void __iomem *base); int
>>>>>> +intelvipfb_remove(struct device *dev); int
>>>>>> +intelvipfb_setup_crtc(struct drm_device *drm); int
>>>>>> +intelvipfb_drm_conn_init(struct drm_device *drm);
>>>>>> +
>>>>>> +struct intelvipfb_priv {
>>>>>> +     struct drm_fbdev_cma *fbcma;
>>>>>> +     struct drm_device *drm;
>>>>>> +     struct fb_info info;
>>>>>> +     void    __iomem         *base;
>>>>>> +};
>>>>>> +
>>>>>> +#endif
>>>>>> diff --git a/drivers/gpu/drm/ivip/intel_vip_of.c
>>>>>> b/drivers/gpu/drm/ivip/intel_vip_of.c
>>>>>> new file mode 100644
>>>>>> index 0000000..17dff36
>>>>>> --- /dev/null
>>>>>> +++ b/drivers/gpu/drm/ivip/intel_vip_of.c
>>>>>> @@ -0,0 +1,146 @@
>>>>>> +/*
>>>>>> + * intel_vip_of.c -- Intel Video and Image Processing(VIP)
>>>>>> + * Frame Buffer II driver
>>>>>> + *
>>>>>> + * This driver supports the Intel VIP Frame Reader component.
>>>>>> + * More info on the hardware can be found in the Intel Video
>>>>>> + * and Image Processing Suite User Guide at this address
>>>>>> + * http://www.altera.com/literature/ug/ug_vip.pdf.
>>>>>> + *
>>>>>> + * 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.
>>>>>> + *
>>>>>> + * 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.
>>>>>> + *
>>>>>> + * Authors:
>>>>>> + * Ong, Hean-Loong <hean.loong.ong@intel.com>
>>>>>> + *
>>>>>> + */
>>>>>> +
>>>>>> +#include <linux/fb.h>
>>>>>> +#include <linux/init.h>
>>>>>> +#include <linux/kernel.h>
>>>>>> +#include <linux/module.h>
>>>>>> +#include <linux/platform_device.h>
>>>>>> +
>>>>>> +#include <drm/drm_fb_helper.h>
>>>>>> +#include "intel_vip_drv.h"
>>>>>> +
>>>>>> +/*
>>>>>> + * Setting up information derived from OF Device Tree Nodes
>>>>>> + * max-width, max-height, bits per pixel, memory port width  */
>>>>>> +
>>>>>> +static int intelvipfb_of_setup(struct intelvipfb_priv *fbdata,
>>>>>> +                            struct platform_device *pdev) {
>>>>>> +     int ret;
>>>>>> +     int mem_word_width;
>>>>>> +     u32 bits_per_color;
>>>>>> +     struct device_node *np = pdev->dev.of_node;
>>>>>> +
>>>>>> +     ret = of_property_read_u32(np, "altr,max-width",
>>>>>> +                                &fbdata->info.var.xres);
>>>>>> +     if (ret) {
>>>>>> +             dev_err(&pdev->dev,
>>>>>> +                     "Missing required parameter 'altr,max-
>>>>>> width'");
>>>>>> +             return ret;
>>>>>> +     }
>>>>>> +     fbdata->info.var.xres_virtual = fbdata->info.var.xres;
>>>>>> +
>>>>>> +     ret = of_property_read_u32(np, "altr,max-height",
>>>>>> +                                &fbdata->info.var.yres);
>>>>>> +     if (ret) {
>>>>>> +             dev_err(&pdev->dev,
>>>>>> +                     "Missing required parameter 'altr,max-
>>>>>> height'");
>>>>>> +             return ret;
>>>>>> +     }
>>>>>> +     fbdata->info.var.yres_virtual = fbdata->info.var.yres;
>>>>>> +
>>>>>> +     ret = of_property_read_u32(np, "altr,bits-per-symbol",
>>>>>> &bits_per_color);
>>>>>> +     if (ret) {
>>>>>> +             dev_err(&pdev->dev,
>>>>>> +                     "Missing required parameter 'altr,bits-per-
>>>>>> symbol'");
>>>>>> +             return ret;
>>>>>> +     }
>>>>>> +
>>>>>> +     fbdata->info.var.bits_per_pixel = bits_per_color *
>>>>>> BYTES_PER_PIXEL;
>>>>>> +
>>>>>> +     ret = of_property_read_u32(np, "altr,mem-port-width",
>>>>>> &mem_word_width);
>>>>>> +     if (ret) {
>>>>>> +             dev_err(&pdev->dev,
>>>>>> +                     "Missing required parameter 'altr,mem-port-
>>>>>> width '");
>>>>>> +             return ret;
>>>>>> +     }
>>>>>> +
>>>>>> +     if (!(mem_word_width >= 32 && mem_word_width % 32 == 0)) {
>>>>>> +             dev_err(&pdev->dev,
>>>>>> +                     "mem-word-width is set to %i. must be >= 32
>>>>>> and multiple of 32.",
>>>>>> +                      mem_word_width);
>>>>>> +             return -ENODEV;
>>>>>> +     }
>>>>>> +
>>>>>> +     return 0;
>>>>>> +}
>>>>>> +
>>>>>> +static int intelvipfb_of_probe(struct platform_device *pdev) {
>>>>>> +     int retval;
>>>>>> +     struct resource *reg_res;
>>>>>> +     struct intelvipfb_priv *fbdata;
>>>>>> +
>>>>>> +     fbdata = devm_kzalloc(&pdev->dev, sizeof(*fbdata),
>>>>>> GFP_KERNEL);
>>>>>> +     if (!fbdata)
>>>>>> +             return -ENOMEM;
>>>>>> +
>>>>>> +     reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>>>> +     if (!reg_res)
>>>>>> +             return -ENOMEM;
>>>>>> +
>>>>>> +     fbdata->base = devm_ioremap_resource(&pdev->dev, reg_res);
>>>>>> +
>>>>>> +     if (IS_ERR(fbdata->base)) {
>>>>>> +             dev_err(&pdev->dev, "devm_ioremap_resource
>>>>>> failed\n");
>>>>>> +             retval = PTR_ERR(fbdata->base);
>>>>>> +             return -ENOMEM;
>>>>>> +     }
>>>>>> +
>>>>>> +     intelvipfb_of_setup(fbdata, pdev);
>>>>>> +
>>>>>> +     platform_set_drvdata(pdev, fbdata);
>>>>>> +
>>>>>> +     return intelvipfb_probe(&pdev->dev, fbdata->base); }
>>>>>> +
>>>>>> +static int intelvipfb_of_remove(struct platform_device *pdev) {
>>>>>> +     return intelvipfb_remove(&pdev->dev); }
>>>>>> +
>>>>>> +/*
>>>>>> + * The name vip-frame-buffer-2.0 is derived from
>>>>>> + * http://www.altera.com/literature/ug/ug_vip.pdf
>>>>>> + * frame buffer IP cores section 14  */
>>>>>> +
>>>>>> +static const struct of_device_id intelvipfb_of_match[] = {
>>>>>> +     { .compatible = "altr,vip-frame-buffer-2.0" },
>>>>>> +     {},
>>>>>> +};
>>>>>> +
>>>>>> +MODULE_DEVICE_TABLE(of, intelvipfb_of_match);
>>>>>> +
>>>>>> +static struct platform_driver intelvipfb_driver = {
>>>>>> +     .probe = intelvipfb_of_probe,
>>>>>> +     .remove = intelvipfb_of_remove,
>>>>>> +     .driver = {
>>>>>> +             .name = DRIVER_NAME,
>>>>>> +             .of_match_table = intelvipfb_of_match,
>>>>>> +     },
>>>>>> +};
>>>>>> +
>>>>>> +module_platform_driver(intelvipfb_driver);
>>>>>> --
>>>>>> 1.7.1
>>>>>>
>>>>>>
>>>>>> -----Original Message-----
>>>>>> From: Ong, Hean Loong
>>>>>> Sent: Friday, March 31, 2017 5:09 PM
>>>>>> To: Vetter, Daniel <daniel.vetter@intel.com>; airlied@linux.ie
>>>>>> Cc: dri-devel@lists.freedesktop.org
>>>>>> Subject: DRM Display driver for Intel FPGA Video and Image
>>>>>> Processing Suite
>>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> I would like to upstream the attached Intel FPGA Video and Image
>>>>>> Processing Suite. The attached patch supports the Intel Arria10
>>>>>> devkit and its variants. The purpose of the patch is to enable the
>>>>>> FPGA driven display designed from the Intel Quartus FPGA design
>>>>>> suite.
>>>>>>
>>>>>> The driver is required as part of the Intel Arria10 devkit
>>>>>> reference design. The driver was tested on:
>>>>>> - The Open Embedded Angstrom Distro.
>>>>>> - The matchbox-terminal and window-manager was used for functional
>>>>>> testing
>>>>>>
>>>>>> Current the intention of the driver is meant to validate the FPGA
>>>>>> designs on the Arria10 devkit for Display Port connecter. We have
>>>>>> not verified its performance of or stability in 3D acceleration or
>>>>>> other non Intel FPGA hardware
>>>>>>
>>>>>> BR
>>>>>>
>>>>>> Hean Loong
>>>>> _______________________________________________
>>>>> dri-devel mailing list
>>>>> dri-devel@lists.freedesktop.org
>>>>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>>>>
>>>>
>>>>
>>>>--
>>>>Daniel Vetter
>>>>Software Engineer, Intel Corporation
>>>>+41 (0) 79 365 57 48 - http://blog.ffwll.ch
>>
>>
>>
>>--
>>Daniel Vetter
>>Software Engineer, Intel Corporation
>>+41 (0) 79 365 57 48 - http://blog.ffwll.ch



-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2017-04-10  7:53 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-31  9:08 DRM Display driver for Intel FPGA Video and Image Processing Suite Ong, Hean Loong
2017-04-02 12:42 ` Daniel Vetter
2017-04-04  4:01 ` Ong, Hean Loong
2017-04-06  6:29   ` Ong, Hean Loong
2017-04-07 16:31     ` Daniel Vetter
2017-04-08  5:41       ` Ong, Hean Loong
2017-04-08 16:31         ` Daniel Vetter
2017-04-10  7:49           ` Ong, Hean Loong
2017-04-10  7:53             ` Daniel Vetter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.