From ace9429bb58fd418f0c81d4c2835699bddf6bde6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:27:49 +0200 Subject: Adding upstream version 6.6.15. Signed-off-by: Daniel Baumann --- drivers/gpu/drm/stm/Kconfig | 22 + drivers/gpu/drm/stm/Makefile | 8 + drivers/gpu/drm/stm/drv.c | 258 ++++ drivers/gpu/drm/stm/dw_mipi_dsi-stm.c | 602 ++++++++++ drivers/gpu/drm/stm/ltdc.c | 2103 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/stm/ltdc.h | 65 + 6 files changed, 3058 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/dw_mipi_dsi-stm.c create mode 100644 drivers/gpu/drm/stm/ltdc.c create mode 100644 drivers/gpu/drm/stm/ltdc.h (limited to 'drivers/gpu/drm/stm') diff --git a/drivers/gpu/drm/stm/Kconfig b/drivers/gpu/drm/stm/Kconfig new file mode 100644 index 000000000..fa49cde43 --- /dev/null +++ b/drivers/gpu/drm/stm/Kconfig @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-only +config DRM_STM + tristate "DRM Support for STMicroelectronics SoC Series" + depends on DRM && ARCH_STM32 + select DRM_KMS_HELPER + select DRM_GEM_DMA_HELPER + select DRM_PANEL_BRIDGE + select VIDEOMODE_HELPERS + select FB_PROVIDE_GET_FB_UNMAPPED_AREA if FB + + 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. + +config DRM_STM_DSI + tristate "STMicroelectronics specific extensions for Synopsys MIPI DSI" + depends on DRM_STM + select DRM_DW_MIPI_DSI + help + Choose this option for MIPI DSI support on STMicroelectronics SoC. diff --git a/drivers/gpu/drm/stm/Makefile b/drivers/gpu/drm/stm/Makefile new file mode 100644 index 000000000..4df5caf01 --- /dev/null +++ b/drivers/gpu/drm/stm/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0-only +stm-drm-y := \ + drv.o \ + ltdc.o + +obj-$(CONFIG_DRM_STM_DSI) += dw_mipi_dsi-stm.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 000000000..e8523abef --- /dev/null +++ b/drivers/gpu/drm/stm/drv.c @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) STMicroelectronics SA 2017 + * + * Authors: Philippe Cornu + * Yannick Fertre + * Fabien Dessenne + * Mickael Reulier + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ltdc.h" + +#define STM_MAX_FB_WIDTH 2048 +#define STM_MAX_FB_HEIGHT 2048 /* same as width to handle orientation */ + +static const struct drm_mode_config_funcs drv_mode_config_funcs = { + .fb_create = drm_gem_fb_create, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +static int stm_gem_dma_dumb_create(struct drm_file *file, + struct drm_device *dev, + struct drm_mode_create_dumb *args) +{ + unsigned int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8); + + /* + * in order to optimize data transfer, pitch is aligned on + * 128 bytes, height is aligned on 4 bytes + */ + args->pitch = roundup(min_pitch, 128); + args->height = roundup(args->height, 4); + + return drm_gem_dma_dumb_create_internal(file, dev, args); +} + +DEFINE_DRM_GEM_DMA_FOPS(drv_driver_fops); + +static const struct drm_driver drv_driver = { + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, + .name = "stm", + .desc = "STMicroelectronics SoC DRM", + .date = "20170330", + .major = 1, + .minor = 0, + .patchlevel = 0, + .fops = &drv_driver_fops, + DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(stm_gem_dma_dumb_create), +}; + +static int drv_load(struct drm_device *ddev) +{ + struct platform_device *pdev = to_platform_device(ddev->dev); + struct ltdc_device *ldev; + int ret; + + DRM_DEBUG("%s\n", __func__); + + ldev = devm_kzalloc(ddev->dev, sizeof(*ldev), GFP_KERNEL); + if (!ldev) + return -ENOMEM; + + ddev->dev_private = (void *)ldev; + + ret = drmm_mode_config_init(ddev); + if (ret) + return ret; + + /* + * 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; + ddev->mode_config.normalize_zpos = true; + + ret = ltdc_load(ddev); + if (ret) + return ret; + + drm_mode_config_reset(ddev); + drm_kms_helper_poll_init(ddev); + + platform_set_drvdata(pdev, ddev); + + return 0; +} + +static void drv_unload(struct drm_device *ddev) +{ + DRM_DEBUG("%s\n", __func__); + + drm_kms_helper_poll_fini(ddev); + drm_atomic_helper_shutdown(ddev); + ltdc_unload(ddev); +} + +static __maybe_unused int drv_suspend(struct device *dev) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct ltdc_device *ldev = ddev->dev_private; + struct drm_atomic_state *state; + + WARN_ON(ldev->suspend_state); + + state = drm_atomic_helper_suspend(ddev); + if (IS_ERR(state)) + return PTR_ERR(state); + + ldev->suspend_state = state; + pm_runtime_force_suspend(dev); + + return 0; +} + +static __maybe_unused int drv_resume(struct device *dev) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct ltdc_device *ldev = ddev->dev_private; + int ret; + + if (WARN_ON(!ldev->suspend_state)) + return -ENOENT; + + pm_runtime_force_resume(dev); + ret = drm_atomic_helper_resume(ddev, ldev->suspend_state); + if (ret) + pm_runtime_force_suspend(dev); + + ldev->suspend_state = NULL; + + return ret; +} + +static __maybe_unused int drv_runtime_suspend(struct device *dev) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + + DRM_DEBUG_DRIVER("\n"); + ltdc_suspend(ddev); + + return 0; +} + +static __maybe_unused int drv_runtime_resume(struct device *dev) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + + DRM_DEBUG_DRIVER("\n"); + return ltdc_resume(ddev); +} + +static const struct dev_pm_ops drv_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(drv_suspend, drv_resume) + SET_RUNTIME_PM_OPS(drv_runtime_suspend, + drv_runtime_resume, NULL) +}; + +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__); + + ret = drm_aperture_remove_framebuffers(&drv_driver); + if (ret) + return ret; + + 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_put; + + ret = drm_dev_register(ddev, 0); + if (ret) + goto err_put; + + drm_fbdev_dma_setup(ddev, 16); + + return 0; + +err_put: + drm_dev_put(ddev); + + return ret; +} + +static void 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_put(ddev); +} + +static void stm_drm_platform_shutdown(struct platform_device *pdev) +{ + drm_atomic_helper_shutdown(platform_get_drvdata(pdev)); +} + +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_new = stm_drm_platform_remove, + .shutdown = stm_drm_platform_shutdown, + .driver = { + .name = "stm32-display", + .of_match_table = drv_dt_ids, + .pm = &drv_pm_ops, + }, +}; + +drm_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/dw_mipi_dsi-stm.c b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c new file mode 100644 index 000000000..d5f8c923d --- /dev/null +++ b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c @@ -0,0 +1,602 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) STMicroelectronics SA 2017 + * + * Authors: Philippe Cornu + * Yannick Fertre + */ + +#include +#include +#include +#include +#include +#include + +#include