cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

drv.c (5873B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) STMicroelectronics SA 2017
      4 *
      5 * Authors: Philippe Cornu <philippe.cornu@st.com>
      6 *          Yannick Fertre <yannick.fertre@st.com>
      7 *          Fabien Dessenne <fabien.dessenne@st.com>
      8 *          Mickael Reulier <mickael.reulier@st.com>
      9 */
     10
     11#include <linux/component.h>
     12#include <linux/dma-mapping.h>
     13#include <linux/module.h>
     14#include <linux/of_platform.h>
     15#include <linux/pm_runtime.h>
     16
     17#include <drm/drm_aperture.h>
     18#include <drm/drm_atomic.h>
     19#include <drm/drm_atomic_helper.h>
     20#include <drm/drm_drv.h>
     21#include <drm/drm_fb_cma_helper.h>
     22#include <drm/drm_fb_helper.h>
     23#include <drm/drm_gem_cma_helper.h>
     24#include <drm/drm_gem_framebuffer_helper.h>
     25#include <drm/drm_module.h>
     26#include <drm/drm_probe_helper.h>
     27#include <drm/drm_vblank.h>
     28
     29#include "ltdc.h"
     30
     31#define STM_MAX_FB_WIDTH	2048
     32#define STM_MAX_FB_HEIGHT	2048 /* same as width to handle orientation */
     33
     34static const struct drm_mode_config_funcs drv_mode_config_funcs = {
     35	.fb_create = drm_gem_fb_create,
     36	.atomic_check = drm_atomic_helper_check,
     37	.atomic_commit = drm_atomic_helper_commit,
     38};
     39
     40static int stm_gem_cma_dumb_create(struct drm_file *file,
     41				   struct drm_device *dev,
     42				   struct drm_mode_create_dumb *args)
     43{
     44	unsigned int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
     45
     46	/*
     47	 * in order to optimize data transfer, pitch is aligned on
     48	 * 128 bytes, height is aligned on 4 bytes
     49	 */
     50	args->pitch = roundup(min_pitch, 128);
     51	args->height = roundup(args->height, 4);
     52
     53	return drm_gem_cma_dumb_create_internal(file, dev, args);
     54}
     55
     56DEFINE_DRM_GEM_CMA_FOPS(drv_driver_fops);
     57
     58static const struct drm_driver drv_driver = {
     59	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
     60	.name = "stm",
     61	.desc = "STMicroelectronics SoC DRM",
     62	.date = "20170330",
     63	.major = 1,
     64	.minor = 0,
     65	.patchlevel = 0,
     66	.fops = &drv_driver_fops,
     67	DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(stm_gem_cma_dumb_create),
     68};
     69
     70static int drv_load(struct drm_device *ddev)
     71{
     72	struct platform_device *pdev = to_platform_device(ddev->dev);
     73	struct ltdc_device *ldev;
     74	int ret;
     75
     76	DRM_DEBUG("%s\n", __func__);
     77
     78	ldev = devm_kzalloc(ddev->dev, sizeof(*ldev), GFP_KERNEL);
     79	if (!ldev)
     80		return -ENOMEM;
     81
     82	ddev->dev_private = (void *)ldev;
     83
     84	ret = drmm_mode_config_init(ddev);
     85	if (ret)
     86		return ret;
     87
     88	/*
     89	 * set max width and height as default value.
     90	 * this value would be used to check framebuffer size limitation
     91	 * at drm_mode_addfb().
     92	 */
     93	ddev->mode_config.min_width = 0;
     94	ddev->mode_config.min_height = 0;
     95	ddev->mode_config.max_width = STM_MAX_FB_WIDTH;
     96	ddev->mode_config.max_height = STM_MAX_FB_HEIGHT;
     97	ddev->mode_config.funcs = &drv_mode_config_funcs;
     98
     99	ret = ltdc_load(ddev);
    100	if (ret)
    101		return ret;
    102
    103	drm_mode_config_reset(ddev);
    104	drm_kms_helper_poll_init(ddev);
    105
    106	platform_set_drvdata(pdev, ddev);
    107
    108	return 0;
    109}
    110
    111static void drv_unload(struct drm_device *ddev)
    112{
    113	DRM_DEBUG("%s\n", __func__);
    114
    115	drm_kms_helper_poll_fini(ddev);
    116	ltdc_unload(ddev);
    117}
    118
    119static __maybe_unused int drv_suspend(struct device *dev)
    120{
    121	struct drm_device *ddev = dev_get_drvdata(dev);
    122	struct ltdc_device *ldev = ddev->dev_private;
    123	struct drm_atomic_state *state;
    124
    125	WARN_ON(ldev->suspend_state);
    126
    127	state = drm_atomic_helper_suspend(ddev);
    128	if (IS_ERR(state))
    129		return PTR_ERR(state);
    130
    131	ldev->suspend_state = state;
    132	pm_runtime_force_suspend(dev);
    133
    134	return 0;
    135}
    136
    137static __maybe_unused int drv_resume(struct device *dev)
    138{
    139	struct drm_device *ddev = dev_get_drvdata(dev);
    140	struct ltdc_device *ldev = ddev->dev_private;
    141	int ret;
    142
    143	if (WARN_ON(!ldev->suspend_state))
    144		return -ENOENT;
    145
    146	pm_runtime_force_resume(dev);
    147	ret = drm_atomic_helper_resume(ddev, ldev->suspend_state);
    148	if (ret)
    149		pm_runtime_force_suspend(dev);
    150
    151	ldev->suspend_state = NULL;
    152
    153	return ret;
    154}
    155
    156static __maybe_unused int drv_runtime_suspend(struct device *dev)
    157{
    158	struct drm_device *ddev = dev_get_drvdata(dev);
    159
    160	DRM_DEBUG_DRIVER("\n");
    161	ltdc_suspend(ddev);
    162
    163	return 0;
    164}
    165
    166static __maybe_unused int drv_runtime_resume(struct device *dev)
    167{
    168	struct drm_device *ddev = dev_get_drvdata(dev);
    169
    170	DRM_DEBUG_DRIVER("\n");
    171	return ltdc_resume(ddev);
    172}
    173
    174static const struct dev_pm_ops drv_pm_ops = {
    175	SET_SYSTEM_SLEEP_PM_OPS(drv_suspend, drv_resume)
    176	SET_RUNTIME_PM_OPS(drv_runtime_suspend,
    177			   drv_runtime_resume, NULL)
    178};
    179
    180static int stm_drm_platform_probe(struct platform_device *pdev)
    181{
    182	struct device *dev = &pdev->dev;
    183	struct drm_device *ddev;
    184	int ret;
    185
    186	DRM_DEBUG("%s\n", __func__);
    187
    188	ret = drm_aperture_remove_framebuffers(false, &drv_driver);
    189	if (ret)
    190		return ret;
    191
    192	dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
    193
    194	ddev = drm_dev_alloc(&drv_driver, dev);
    195	if (IS_ERR(ddev))
    196		return PTR_ERR(ddev);
    197
    198	ret = drv_load(ddev);
    199	if (ret)
    200		goto err_put;
    201
    202	ret = drm_dev_register(ddev, 0);
    203	if (ret)
    204		goto err_put;
    205
    206	drm_fbdev_generic_setup(ddev, 16);
    207
    208	return 0;
    209
    210err_put:
    211	drm_dev_put(ddev);
    212
    213	return ret;
    214}
    215
    216static int stm_drm_platform_remove(struct platform_device *pdev)
    217{
    218	struct drm_device *ddev = platform_get_drvdata(pdev);
    219
    220	DRM_DEBUG("%s\n", __func__);
    221
    222	drm_dev_unregister(ddev);
    223	drv_unload(ddev);
    224	drm_dev_put(ddev);
    225
    226	return 0;
    227}
    228
    229static const struct of_device_id drv_dt_ids[] = {
    230	{ .compatible = "st,stm32-ltdc"},
    231	{ /* end node */ },
    232};
    233MODULE_DEVICE_TABLE(of, drv_dt_ids);
    234
    235static struct platform_driver stm_drm_platform_driver = {
    236	.probe = stm_drm_platform_probe,
    237	.remove = stm_drm_platform_remove,
    238	.driver = {
    239		.name = "stm32-display",
    240		.of_match_table = drv_dt_ids,
    241		.pm = &drv_pm_ops,
    242	},
    243};
    244
    245drm_module_platform_driver(stm_drm_platform_driver);
    246
    247MODULE_AUTHOR("Philippe Cornu <philippe.cornu@st.com>");
    248MODULE_AUTHOR("Yannick Fertre <yannick.fertre@st.com>");
    249MODULE_AUTHOR("Fabien Dessenne <fabien.dessenne@st.com>");
    250MODULE_AUTHOR("Mickael Reulier <mickael.reulier@st.com>");
    251MODULE_DESCRIPTION("STMicroelectronics ST DRM LTDC driver");
    252MODULE_LICENSE("GPL v2");