DRM Display driver for Intel FPGA Video and Image Processing Suite

Daniel Vetter daniel at ffwll.ch
Sat Apr 8 16:31:29 UTC 2017


On Sat, Apr 8, 2017 at 7:41 AM, Ong, Hean Loong
<hean.loong.ong at 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 at ffwll.ch [mailto:daniel.vetter at ffwll.ch] On Behalf Of Daniel
>>Vetter
>>Sent: Saturday, April 8, 2017 12:32 AM
>>To: Ong, Hean Loong <hean.loong.ong at intel.com>
>>Cc: Vetter, Daniel <daniel.vetter at intel.com>; airlied at linux.ie; dri-
>>devel at 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 at 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 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
>>> _______________________________________________
>>> dri-devel mailing list
>>> dri-devel at 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


More information about the dri-devel mailing list