From patchwork Mon Feb 20 16:08:36 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yannick FERTRE X-Patchwork-Id: 9583261 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 2DCAC60578 for ; Mon, 20 Feb 2017 16:32:27 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3B4F0285F8 for ; Mon, 20 Feb 2017 16:32:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2EA3D286ED; Mon, 20 Feb 2017 16:32:27 +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 BD415285F8 for ; Mon, 20 Feb 2017 16:32:24 +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=mWNYLYH2upkh2/C0R4GZAe3RQ1usSeQ6W2ZfpzkxtpU=; b=GR9Kt5rhpmO4fX oZVMxEL6xP306DCeA6AEALR5MrxES9rVoJJZJokLwsauWtr9Ch3wwyUQ6mWgBj1HvxM+NmNGXl9Er vAKHAlI6owFH2YGNgNGQ2h+qQKEIoQGnf6PNPhiYpdU/zdAGXVHZqShxV/dcyDHFnB7QkLQ8TUEHJ EVvvLbGscG7Pc9HVdrBYiOo4DYxG+a2AOynd4YaruDlzibxBKGaK5TtTaQwgF9DG61xMjy6jda81n wqNasLHYhS/ypXApjUygY7y7RU1jnICakXnmf5Ho/hlkzq4gdTQijnTpyFcjOsHxiwprVeQ3U+xMg hiKpTJDBkfkvxpEvjJbA==; 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 1cfqsx-0004MP-6P; Mon, 20 Feb 2017 16:32:23 +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 1cfqWr-0006lQ-SC for linux-arm-kernel@lists.infradead.org; Mon, 20 Feb 2017 16:09:46 +0000 Received: from pps.filterd (m0046668.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.0.11/8.16.0.11) with SMTP id v1KG7hln031934; Mon, 20 Feb 2017 17:08:49 +0100 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-.pphosted.com with ESMTP id 28pcm256p4-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Mon, 20 Feb 2017 17:08:48 +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 CA39D31; Mon, 20 Feb 2017 16:08:47 +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 354B92B3B; Mon, 20 Feb 2017 16:08:47 +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; Mon, 20 Feb 2017 17:08:46 +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 v3 2/7] drm/st: Add STM32 LTDC driver Date: Mon, 20 Feb 2017 17:08:36 +0100 Message-ID: <1487606921-26981-3-git-send-email-yannick.fertre@st.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1487606921-26981-1-git-send-email-yannick.fertre@st.com> References: <1487606921-26981-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-02-20_14:, , signatures=0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170220_080934_645424_9C530882 X-CRM114-Status: GOOD ( 21.86 ) 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 patch adds support for the STM32 LCD-TFT display controller. Signed-off-by: Yannick Fertre --- drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/stm/Kconfig | 14 + drivers/gpu/drm/stm/Makefile | 7 + drivers/gpu/drm/stm/drv.c | 232 +++++++ drivers/gpu/drm/stm/drv.h | 24 + drivers/gpu/drm/stm/ltdc.c | 1381 ++++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/stm/ltdc.h | 22 + 8 files changed, 1683 insertions(+) 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 90bc65d..b6dea28 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -237,6 +237,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 92de399..a4bcb95 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..2b91db6 --- /dev/null +++ b/drivers/gpu/drm/stm/Kconfig @@ -0,0 +1,14 @@ +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 + help + Choose this option if you have an ST STMicroelectronics SoC. + + 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..d98b6a1 --- /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 ST_MAX_FB_WIDTH 2048 +#define ST_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 = ST_MAX_FB_WIDTH; + ddev->mode_config.max_height = ST_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..82ba53b --- /dev/null +++ b/drivers/gpu/drm/stm/drv.h @@ -0,0 +1,24 @@ +/* + * 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; +}; + +extern struct platform_driver ltdc_driver; + +#endif diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c new file mode 100644 index 0000000..148607d --- /dev/null +++ b/drivers/gpu/drm/stm/ltdc.c @@ -0,0 +1,1381 @@ +/* + * 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 + +#include