On Tue, 2017-08-01 at 17:30 +0300, Laurent Pinchart wrote:
Hi Hean Loong,
Thank you for the patch.
On Tuesday 01 Aug 2017 10:31:34 Hean Loong, Ong wrote:
From: Ong Hean Loong hean.loong.ong@intel.com
Driver for Intel FPGA Video and Image Processing Suite Frame Buffer II. The driver only supports the Intel Arria10 devkit and its variants. This driver can be either loaded staticlly or in modules. The OF device tree binding is located at: Documentation/devicetree/bindings/display/altr,vip-fb2.txt
Signed-off-by: Ong, Hean Loong hean.loong.ong@intel.com
V3: *Changes to fixing drm_simple_pipe *Used drm_fb_cma_get_gem_addr
V2:
*Adding drm_simple_display_pipe_init
drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/ivip/Kconfig | 13 +++ drivers/gpu/drm/ivip/Makefile | 9 ++ drivers/gpu/drm/ivip/intel_vip_conn.c | 96 ++++++++++++++++ drivers/gpu/drm/ivip/intel_vip_core.c | 183 ++++++++++++++++++++++++++++++ drivers/gpu/drm/ivip/intel_vip_drv.h | 54 +++++++++ drivers/gpu/drm/ivip/intel_vip_of.c | 204 +++++++++++++++++++++++++++++++ 8 files changed, 562 insertions(+) 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_drv.h create mode 100644 drivers/gpu/drm/ivip/intel_vip_of.c
[snip]
diff --git a/drivers/gpu/drm/ivip/Kconfig b/drivers/gpu/drm/ivip/Kconfig new file mode 100644 index 0000000..9a8c5ce --- /dev/null +++ b/drivers/gpu/drm/ivip/Kconfig @@ -0,0 +1,13 @@ +config DRM_IVIP
- tristate "Intel FGPA Video and Image Processing"
- depends on DRM && OF
- 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.
I think this should be fixed to upstream this driver.
Note that ACPI and X_86 architecture is yet
ACPI on FPGA... I wonder if it could get any crazier than that :-)
The driver is meant for the product Intel FPGA Arria10 devkit. We do not have plans for the devkit to be shipped with ACPI and X_86 in a forseeable future. Currently most the commercial SoC devkits are shipped with ARM + FPGA.
- to be supported.If M is selected the module would be
called ivip.
s/.If/. If/
[snip]
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..ea85715 --- /dev/null +++ b/drivers/gpu/drm/ivip/intel_vip_core.c @@ -0,0 +1,183 @@ +/*
- 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
- 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_plane_helper.h> +#include <drm/drm_simple_kms_helper.h>
+#include "intel_vip_drv.h"
+static void intelvipfb_enable(struct drm_simple_display_pipe *pipe,
- struct drm_crtc_state *crtc_state)
+{
- /*
- * 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;
- struct intelvipfb_priv *priv = pipe->plane.dev-
dev_private;
- void __iomem *base = priv->base;
- struct drm_plane_state *state = pipe->plane.state;
- dma_addr_t addr;
- addr = drm_fb_cma_get_gem_addr(state->fb, state, 0);
- dev_info(pipe->plane.dev->dev, "Address 0x%x\n", addr);
- 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(struct drm_simple_display_pipe *pipe) +{
- struct intelvipfb_priv *priv = pipe->plane.dev-
dev_private;
- void __iomem *base = priv->base;
Missing blank line.
- /* set the control register to 0 to stop streaming */
- writel(0, base + INTELVIPFB_CONTROL);
+}
+static const struct drm_mode_config_funcs intelvipfb_mode_config_funcs = {
- .fb_create = drm_fb_cma_create,
- .atomic_check = drm_atomic_helper_check,
- .atomic_commit = drm_atomic_helper_commit,
+};
+static void intelvipfb_setup_mode_config(struct drm_device *drm) +{
- drm_mode_config_init(drm);
- drm->mode_config.funcs = &intelvipfb_mode_config_funcs;
+}
+static int intelvipfb_pipe_prepare_fb(struct drm_simple_display_pipe *pipe,
struct drm_plane_state *plane_state)
+{
- return drm_fb_cma_prepare_fb(&pipe->plane, plane_state);
+}
+static void intelvipfb_update(struct drm_simple_display_pipe *pipe,
struct drm_plane_state *old_state)
+{
- struct drm_crtc *crtc = &pipe->crtc;
- if (crtc->state->event) {
spin_lock_irq(&crtc->dev->event_lock);
drm_crtc_send_vblank_event(crtc, crtc->state-
event);
spin_unlock_irq(&crtc->dev->event_lock);
crtc->state->event = NULL;
- }
This is not quite right. Userspace expects the driver to perform a page flip here, and you just signal page flip completion without doing anything.
+}
+static struct drm_simple_display_pipe_funcs fbpriv_funcs = {
- .prepare_fb = intelvipfb_pipe_prepare_fb,
- .update = intelvipfb_update,
- .enable = intelvipfb_enable,
- .disable = intelvipfb_disable
+};
+int intelvipfb_probe(struct device *dev, void __iomem *base)
You don't use the base argument, you can remove it.
+{
- int retval;
- struct drm_device *drm;
- struct intelvipfb_priv *fbpriv = dev_get_drvdata(dev);
- struct drm_connector *connector;
Extra blank line.
- u32 formats[] = {DRM_FORMAT_XRGB8888};
- dev_set_drvdata(dev, fbpriv);
As fbpriv is obtained by a call to dev_get_drvdata(), this isn't needed.
A better option would be to pass the intelvipfb_priv pointer as an argument to this function.
- drm = fbpriv->drm;
- drm->dev_private = fbpriv;
- intelvipfb_setup_mode_config(drm);
- connector = intelvipfb_conn_setup(drm);
- if (!connector) {
dev_err(drm->dev, "Connector setup failed\n");
goto err_mode_config;
- }
- retval = drm_simple_display_pipe_init(drm, &fbpriv->pipe,
&fbpriv_funcs, formats,
ARRAY_SIZE(formats), connector);
- if (retval < 0) {
dev_err(drm->dev, "Cannot setup simple display
pipe\n");
goto err_mode_config;
- }
- fbpriv->fbcma = drm_fbdev_cma_init(drm,
drm->mode_config.preferred_depth,
drm->mode_config.num_connector);
- drm_mode_config_reset(drm);
- drm_dev_register(drm, 0);
- return retval;
+err_mode_config:
- drm_mode_config_cleanup(drm);
- return -ENODEV;
+} +EXPORT_SYMBOL_GPL(intelvipfb_probe);
Why do you need to export this symbol ?
+int intelvipfb_remove(struct device *dev) +{
- struct intelvipfb_priv *fbpriv = dev_get_drvdata(dev);
- struct drm_device *drm = fbpriv->drm;
- drm_dev_unregister(drm);
- if (fbpriv->fbcma)
drm_fbdev_cma_fini(fbpriv->fbcma);
- drm_mode_config_cleanup(drm);
- drm_dev_unref(drm);
- devm_kfree(dev, fbpriv);
The whole point of devm_kzalloc() is that you don't need to free the memory at remove time.
- 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_drv.h b/drivers/gpu/drm/ivip/intel_vip_drv.h new file mode 100644 index 0000000..ebdbd50 --- /dev/null +++ b/drivers/gpu/drm/ivip/intel_vip_drv.h @@ -0,0 +1,54 @@ +/*
- 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
Missing blank line.
+#include <linux/io.h> +#include <linux/fb.h>
I don't think this header is needed.
+#define DRIVER_NAME "intelvipfb" +#define BYTES_PER_PIXEL 4 +#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); +struct drm_connector *intelvipfb_conn_setup(struct drm_device *drm);
+struct intelvipfb_priv {
- struct drm_simple_display_pipe pipe;
- struct drm_fbdev_cma *fbcma;
- struct drm_device *drm;
- 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..5a7c63b --- /dev/null +++ b/drivers/gpu/drm/ivip/intel_vip_of.c @@ -0,0 +1,204 @@ +/*
- 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
- 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/component.h> +#include <linux/fb.h>
I don't think those two headers are needed.
+#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h>
+#include <drm/drm_fb_helper.h> +#include <drm/drm_of.h> +#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_simple_kms_helper.h>
Please sort these alphabetically.
+#include "intel_vip_drv.h"
+DEFINE_DRM_GEM_CMA_FOPS(drm_fops);
+static void intelvipfb_lastclose(struct drm_device *drm) +{
- struct intelvipfb_priv *priv = drm->dev_private;
- drm_fbdev_cma_restore_mode(priv->fbcma);
+}
+static struct drm_driver intelvipfb_drm = {
- .driver_features =
DRIVER_MODESET | DRIVER_GEM |
DRIVER_PRIME | 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,
- .lastclose = intelvipfb_lastclose,
- .name = DRIVER_NAME,
- .date = "20170729",
- .desc = "Intel FPGA VIP SUITE",
- .major = 1,
- .minor = 0,
- .ioctls = NULL,
- .patchlevel = 0,
- .fops = &drm_fops,
+};
+/*
- Setting up information derived from OF Device Tree Nodes
- max-width, max-height, bits per pixel, memory port width
- */
+static int intelvipfb_drm_setup(struct device *dev,
struct intelvipfb_priv *fbpriv)
+{
- struct drm_device *drm = fbpriv->drm;
- struct device_node *np = dev->of_node;
- int mem_word_width;
- int max_h, max_w;
- int bpp;
- int ret;
- ret = of_property_read_u32(np, "altr,max-width", &max_w);
- if (ret) {
dev_err(dev,
"Missing required parameter 'altr,max-width'");
return ret;
- }
- ret = of_property_read_u32(np, "altr,max-height", &max_h);
- if (ret) {
dev_err(dev,
"Missing required parameter 'altr,max-height'");
return ret;
- }
- ret = of_property_read_u32(np, "altr,bits-per-symbol",
&bpp);
This property is not documented in patch 1/3.
- if (ret) {
dev_err(dev,
"Missing required parameter 'altr,bits-per-
symbol'");
return ret;
- }
- ret = of_property_read_u32(np, "altr,mem-port-width",
&mem_word_width);
- if (ret) {
dev_err(dev, "Missing required parameter
'altr,mem-port-width
'");
return ret;
- }
- if (!(mem_word_width >= 32 && mem_word_width % 32 == 0)) {
dev_err(dev,
"mem-word-width is set to %i. must be >= 32 and
multiple of
32.",
mem_word_width);
return -ENODEV;
- }
- drm->mode_config.min_width = 640;
- drm->mode_config.min_height = 480;
- drm->mode_config.max_width = max_w;
- drm->mode_config.max_height = max_h;
- drm->mode_config.preferred_depth = bpp * BYTES_PER_PIXEL;
- return 0;
+}