From patchwork Wed Mar 15 17:02:08 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yannick FERTRE X-Patchwork-Id: 9626237 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 157D86048C for ; Wed, 15 Mar 2017 17:05:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F0712284CB for ; Wed, 15 Mar 2017 17:05:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E194628639; Wed, 15 Mar 2017 17:05:06 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 6B77F284CB for ; Wed, 15 Mar 2017 17:05:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=Ze20zeZgMPDxllBzhbLNyE+zicQ3f5P891bIntnagt0=; b=oPOR17Oy+LmyfI 0dBdPqZCEKaf5Ios1myiqarA+CpNiZq5QJm8Lox7687YIPyw+TK+eflIysNO+Xl6n/dC1Hf9uhkWa Nrhhxqjc31fHUK3F8jQrgoUWMh4n75JTmJm+0vYZ1aB1ItgD3PN4dxSMO+hmsPQZdM4YDJ51cYlgf vVETtUEc4aKrzjnv1s1UfZm1XuLSSRMMoESKxMefPNoYgkrXfJaQZ0bIMZpAU56EqyoLyCAeVPcEg eCszkMnATezMvfDutBOAa2KaQOn47hYHPso5wPf7SRbhsmw8GwCMv6oQpPgKm2cpk4fAvnrkp/DhL 4y7HDBFu0Elt+3Gli/tA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1coCM8-00027N-2R; Wed, 15 Mar 2017 17:05:00 +0000 Received: from mx07-00178001.pphosted.com ([62.209.51.94]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1coCKS-0000bR-1h for linux-arm-kernel@lists.infradead.org; Wed, 15 Mar 2017 17:03:32 +0000 Received: from pps.filterd (m0046037.ppops.net [127.0.0.1]) by m0046037.ppops.net (8.16.0.11/8.16.0.11) with SMTP id v2FGsLhT016700; Wed, 15 Mar 2017 18:02:21 +0100 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-.pphosted.com with ESMTP id 296guprnnu-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Wed, 15 Mar 2017 18:02:21 +0100 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 7753931; Wed, 15 Mar 2017 17:02:20 +0000 (GMT) Received: from Webmail-eu.st.com (Safex1hubcas23.st.com [10.75.90.46]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 18E922A5E; Wed, 15 Mar 2017 17:02:20 +0000 (GMT) Received: from localhost (10.48.1.53) by webmail-ga.st.com (10.75.90.48) with Microsoft SMTP Server (TLS) id 14.3.319.2; Wed, 15 Mar 2017 18:02:19 +0100 From: Yannick Fertre To: Alexandre TORGUE , Thierry Reding , David Airlie , Maxime Coquelin , Russell King , Mark Rutland , Rob Herring , Arnd Bergmann , Benjamin Gaignard , Yannick Fertre Subject: [PATCH v4 2/8] drm/stm: Add STM32 LTDC driver Date: Wed, 15 Mar 2017 18:02:08 +0100 Message-ID: <1489597334-16896-3-git-send-email-yannick.fertre@st.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1489597334-16896-1-git-send-email-yannick.fertre@st.com> References: <1489597334-16896-1-git-send-email-yannick.fertre@st.com> MIME-Version: 1.0 X-Originating-IP: [10.48.1.53] X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-03-15_06:, , signatures=0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170315_100316_741668_71B24CB2 X-CRM114-Status: GOOD ( 21.57 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, kernel@stlinux.com, Philippe Cornu , Fabien Dessenne , dri-devel@lists.freedesktop.org, Mickael Reulier , Vincent Abriou , Gabriel FERNANDEZ , linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP This controller provides output signals to interface directly a variety of LCD and TFT panels. These output signals are: RGB signals (up to 24bpp), vertical & horizontal synchronisations, data enable and the pixel clock. Change-Id: Ic1d6ade06ab7115c62e98dd21dc3981fb5948d1c Signed-off-by: Yannick Fertre --- drivers/gpu/drm/Kconfig | 3 +- drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/stm/Kconfig | 16 + drivers/gpu/drm/stm/Makefile | 7 + drivers/gpu/drm/stm/drv.c | 232 +++++++ drivers/gpu/drm/stm/drv.h | 22 + drivers/gpu/drm/stm/ltdc.c | 1422 ++++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/stm/ltdc.h | 22 + 8 files changed, 1724 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/stm/Kconfig create mode 100644 drivers/gpu/drm/stm/Makefile create mode 100644 drivers/gpu/drm/stm/drv.c create mode 100644 drivers/gpu/drm/stm/drv.h create mode 100644 drivers/gpu/drm/stm/ltdc.c create mode 100644 drivers/gpu/drm/stm/ltdc.h diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 78d7fc0..dd5762a 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -203,7 +203,6 @@ config DRM_VGEM as used by Mesa's software renderer for enhanced performance. If M is selected the module will be called vgem. - source "drivers/gpu/drm/exynos/Kconfig" source "drivers/gpu/drm/rockchip/Kconfig" @@ -246,6 +245,8 @@ source "drivers/gpu/drm/fsl-dcu/Kconfig" source "drivers/gpu/drm/tegra/Kconfig" +source "drivers/gpu/drm/stm/Kconfig" + source "drivers/gpu/drm/panel/Kconfig" source "drivers/gpu/drm/bridge/Kconfig" diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 59aae43..320fd86 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -81,6 +81,7 @@ obj-$(CONFIG_DRM_BOCHS) += bochs/ obj-$(CONFIG_DRM_VIRTIO_GPU) += virtio/ obj-$(CONFIG_DRM_MSM) += msm/ obj-$(CONFIG_DRM_TEGRA) += tegra/ +obj-$(CONFIG_DRM_STM) += stm/ obj-$(CONFIG_DRM_STI) += sti/ obj-$(CONFIG_DRM_IMX) += imx/ obj-$(CONFIG_DRM_MEDIATEK) += mediatek/ diff --git a/drivers/gpu/drm/stm/Kconfig b/drivers/gpu/drm/stm/Kconfig new file mode 100644 index 0000000..8ef8a09 --- /dev/null +++ b/drivers/gpu/drm/stm/Kconfig @@ -0,0 +1,16 @@ +config DRM_STM + tristate "DRM Support for STMicroelectronics SoC Series" + depends on DRM && (ARCH_STM32 || ARCH_MULTIPLATFORM) + select DRM_KMS_HELPER + select DRM_GEM_CMA_HELPER + select DRM_KMS_CMA_HELPER + select DRM_PANEL + select VIDEOMODE_HELPERS + select FB_PROVIDE_GET_FB_UNMAPPED_AREA + default y + + help + Enable support for the on-chip display controller on + STMicroelectronics STM32 MCUs. + To compile this driver as a module, choose M here: the module + will be called stm-drm. diff --git a/drivers/gpu/drm/stm/Makefile b/drivers/gpu/drm/stm/Makefile new file mode 100644 index 0000000..e114d45 --- /dev/null +++ b/drivers/gpu/drm/stm/Makefile @@ -0,0 +1,7 @@ +ccflags-y := -Iinclude/drm + +stm-drm-y := \ + drv.o \ + ltdc.o + +obj-$(CONFIG_DRM_STM) += stm-drm.o diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c new file mode 100644 index 0000000..d5c46c5 --- /dev/null +++ b/drivers/gpu/drm/stm/drv.c @@ -0,0 +1,232 @@ +/* + * Copyright (C) STMicroelectronics SA 2017 + * + * Authors: Philippe Cornu + * Yannick Fertre + * Fabien Dessenne + * Mickael Reulier + * + * License terms: GNU General Public License (GPL), version 2 + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "drv.h" +#include "ltdc.h" + +#define DRIVER_NAME "stm" +#define DRIVER_DESC "STMicroelectronics SoC DRM" +#define DRIVER_DATE "20170209" +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 0 +#define DRIVER_PATCH_LEVEL 0 + +#define STM_MAX_FB_WIDTH 2048 +#define STM_MAX_FB_HEIGHT 2048 /* same as width to handle orientation */ + +static void drv_output_poll_changed(struct drm_device *ddev) +{ + struct stm_private *priv = ddev->dev_private; + + drm_fbdev_cma_hotplug_event(priv->fbdev); +} + +static const struct drm_mode_config_funcs drv_mode_config_funcs = { + .fb_create = drm_fb_cma_create, + .output_poll_changed = drv_output_poll_changed, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +static const struct file_operations drv_driver_fops = { + .owner = THIS_MODULE, + .open = drm_open, + .release = drm_release, + .unlocked_ioctl = drm_ioctl, + .compat_ioctl = drm_compat_ioctl, + .poll = drm_poll, + .read = drm_read, + .mmap = drm_gem_cma_mmap, + .get_unmapped_area = drm_gem_cma_get_unmapped_area, +}; + +static void drv_lastclose(struct drm_device *ddev) +{ + struct stm_private *priv = ddev->dev_private; + + DRM_DEBUG("%s\n", __func__); + + drm_fbdev_cma_restore_mode(priv->fbdev); +} + +static struct drm_driver drv_driver = { + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | + DRIVER_ATOMIC, + .lastclose = drv_lastclose, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, + .patchlevel = DRIVER_PATCH_LEVEL, + .fops = &drv_driver_fops, + .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_free_object_unlocked = drm_gem_cma_free_object, + .gem_vm_ops = &drm_gem_cma_vm_ops, + .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, + .enable_vblank = ltdc_crtc_enable_vblank, + .disable_vblank = ltdc_crtc_disable_vblank, +}; + +static int drv_load(struct drm_device *ddev) +{ + struct platform_device *pdev = to_platform_device(ddev->dev); + struct drm_fbdev_cma *fbdev; + struct stm_private *priv; + int ret; + + DRM_DEBUG("%s\n", __func__); + + priv = devm_kzalloc(ddev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + ddev->dev_private = (void *)priv; + + drm_mode_config_init(ddev); + + /* + * set max width and height as default value. + * this value would be used to check framebuffer size limitation + * at drm_mode_addfb(). + */ + ddev->mode_config.min_width = 0; + ddev->mode_config.min_height = 0; + ddev->mode_config.max_width = STM_MAX_FB_WIDTH; + ddev->mode_config.max_height = STM_MAX_FB_HEIGHT; + ddev->mode_config.funcs = &drv_mode_config_funcs; + + ret = ltdc_load(ddev); + if (ret) + return ret; + + drm_mode_config_reset(ddev); + drm_kms_helper_poll_init(ddev); + + if (ddev->mode_config.num_connector) { + priv = ddev->dev_private; + fbdev = drm_fbdev_cma_init(ddev, 16, + ddev->mode_config.num_connector); + if (IS_ERR(fbdev)) { + DRM_DEBUG("Warning: fails to create fbdev\n"); + fbdev = NULL; + } + priv->fbdev = fbdev; + } + + platform_set_drvdata(pdev, priv); + + return 0; +} + +static void drv_unload(struct drm_device *ddev) +{ + struct stm_private *priv = ddev->dev_private; + + DRM_DEBUG("%s\n", __func__); + + ltdc_unload(ddev); + + if (priv->fbdev) { + drm_fbdev_cma_fini(priv->fbdev); + priv->fbdev = NULL; + } + + drm_kms_helper_poll_fini(ddev); + drm_vblank_cleanup(ddev); + drm_mode_config_cleanup(ddev); +} + +static int stm_drm_platform_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct drm_device *ddev; + int ret; + + DRM_DEBUG("%s\n", __func__); + + dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); + + ddev = drm_dev_alloc(&drv_driver, dev); + if (IS_ERR(ddev)) + return PTR_ERR(ddev); + + ret = drv_load(ddev); + if (ret) + goto err_unref; + + ret = drm_dev_register(ddev, 0); + if (ret) + goto err_unref; + + return 0; + +err_unref: + drm_dev_unref(ddev); + + return ret; +} + +static int stm_drm_platform_remove(struct platform_device *pdev) +{ + struct drm_device *ddev = platform_get_drvdata(pdev); + + DRM_DEBUG("%s\n", __func__); + + drm_dev_unregister(ddev); + drv_unload(ddev); + drm_dev_unref(ddev); + + return 0; +} + +static const struct of_device_id drv_dt_ids[] = { + { .compatible = "st,stm32-ltdc"}, + { /* end node */ }, +}; +MODULE_DEVICE_TABLE(of, drv_dt_ids); + +static struct platform_driver stm_drm_platform_driver = { + .probe = stm_drm_platform_probe, + .remove = stm_drm_platform_remove, + .driver = { + .name = DRIVER_NAME, + .of_match_table = drv_dt_ids, + }, +}; + +module_platform_driver(stm_drm_platform_driver); + +MODULE_AUTHOR("Philippe Cornu "); +MODULE_AUTHOR("Yannick Fertre "); +MODULE_AUTHOR("Fabien Dessenne "); +MODULE_AUTHOR("Mickael Reulier "); +MODULE_DESCRIPTION("STMicroelectronics ST DRM LTDC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/stm/drv.h b/drivers/gpu/drm/stm/drv.h new file mode 100644 index 0000000..edff073 --- /dev/null +++ b/drivers/gpu/drm/stm/drv.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) STMicroelectronics SA 2017 + * + * Authors: Philippe Cornu + * Yannick Fertre + * Fabien Dessenne + * Mickael Reulier + * + * License terms: GNU General Public License (GPL), version 2 + */ + +#ifndef _DRV_H_ +#define _DRV_H_ + +#include + +struct stm_private { + struct ltdc *ltdc; + struct drm_fbdev_cma *fbdev; +}; + +#endif diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c new file mode 100644 index 0000000..560375d --- /dev/null +++ b/drivers/gpu/drm/stm/ltdc.c @@ -0,0 +1,1422 @@ +/* + * Copyright (C) STMicroelectronics SA 2017 + * + * Authors: Philippe Cornu + * Yannick Fertre + * Fabien Dessenne + * Mickael Reulier + * + * License terms: GNU General Public License (GPL), version 2 + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include