DRM Display driver for Intel FPGA Video and Image Processing Suite
Ong, Hean Loong
hean.loong.ong at intel.com
Tue Apr 4 04:01:24 UTC 2017
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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at intel.com>; airlied at linux.ie
Cc: dri-devel at 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
More information about the dri-devel
mailing list