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@xxxxxxxx [mailto:daniel.vetter@xxxxxxxx] On Behalf Of Daniel >Vetter >Sent: Saturday, April 8, 2017 12:32 AM >To: Ong, Hean Loong <hean.loong.ong@xxxxxxxxx> >Cc: Vetter, Daniel <daniel.vetter@xxxxxxxxx>; airlied@xxxxxxxx; dri- >devel@xxxxxxxxxxxxxxxxxxxxx >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@xxxxxxxxx> >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@xxxxxxxxx> >>> 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@xxxxxxxxx> >>> --- >>> 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@xxxxxxxxx> >>> + * >>> + */ >>> + >>> +#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@xxxxxxxxx> >>> + * >>> + */ >>> + >>> +#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@xxxxxxxxx>"); >>> +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@xxxxxxxxx> >>> + * >>> + */ >>> + >>> +#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@xxxxxxxxx> >>> + * >>> + */ >>> +#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@xxxxxxxxx> >>> + * >>> + */ >>> + >>> +#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@xxxxxxxxx>; airlied@xxxxxxxx >>> Cc: dri-devel@xxxxxxxxxxxxxxxxxxxxx >>> 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@xxxxxxxxxxxxxxxxxxxxx >> 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@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel