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

sti_drv.c (6677B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) STMicroelectronics SA 2014
      4 * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
      5 */
      6
      7#include <linux/component.h>
      8#include <linux/dma-mapping.h>
      9#include <linux/kernel.h>
     10#include <linux/module.h>
     11#include <linux/of_platform.h>
     12
     13#include <drm/drm_atomic.h>
     14#include <drm/drm_atomic_helper.h>
     15#include <drm/drm_debugfs.h>
     16#include <drm/drm_drv.h>
     17#include <drm/drm_fb_cma_helper.h>
     18#include <drm/drm_fb_helper.h>
     19#include <drm/drm_gem_cma_helper.h>
     20#include <drm/drm_gem_framebuffer_helper.h>
     21#include <drm/drm_of.h>
     22#include <drm/drm_probe_helper.h>
     23
     24#include "sti_drv.h"
     25#include "sti_plane.h"
     26
     27#define DRIVER_NAME	"sti"
     28#define DRIVER_DESC	"STMicroelectronics SoC DRM"
     29#define DRIVER_DATE	"20140601"
     30#define DRIVER_MAJOR	1
     31#define DRIVER_MINOR	0
     32
     33#define STI_MAX_FB_HEIGHT	4096
     34#define STI_MAX_FB_WIDTH	4096
     35
     36static int sti_drm_fps_get(void *data, u64 *val)
     37{
     38	struct drm_device *drm_dev = data;
     39	struct drm_plane *p;
     40	unsigned int i = 0;
     41
     42	*val = 0;
     43	list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) {
     44		struct sti_plane *plane = to_sti_plane(p);
     45
     46		*val |= plane->fps_info.output << i;
     47		i++;
     48	}
     49
     50	return 0;
     51}
     52
     53static int sti_drm_fps_set(void *data, u64 val)
     54{
     55	struct drm_device *drm_dev = data;
     56	struct drm_plane *p;
     57	unsigned int i = 0;
     58
     59	list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) {
     60		struct sti_plane *plane = to_sti_plane(p);
     61
     62		memset(&plane->fps_info, 0, sizeof(plane->fps_info));
     63		plane->fps_info.output = (val >> i) & 1;
     64
     65		i++;
     66	}
     67
     68	return 0;
     69}
     70
     71DEFINE_SIMPLE_ATTRIBUTE(sti_drm_fps_fops,
     72			sti_drm_fps_get, sti_drm_fps_set, "%llu\n");
     73
     74static int sti_drm_fps_dbg_show(struct seq_file *s, void *data)
     75{
     76	struct drm_info_node *node = s->private;
     77	struct drm_device *dev = node->minor->dev;
     78	struct drm_plane *p;
     79
     80	list_for_each_entry(p, &dev->mode_config.plane_list, head) {
     81		struct sti_plane *plane = to_sti_plane(p);
     82
     83		seq_printf(s, "%s%s\n",
     84			   plane->fps_info.fps_str,
     85			   plane->fps_info.fips_str);
     86	}
     87
     88	return 0;
     89}
     90
     91static struct drm_info_list sti_drm_dbg_list[] = {
     92	{"fps_get", sti_drm_fps_dbg_show, 0},
     93};
     94
     95static void sti_drm_dbg_init(struct drm_minor *minor)
     96{
     97	drm_debugfs_create_files(sti_drm_dbg_list,
     98				 ARRAY_SIZE(sti_drm_dbg_list),
     99				 minor->debugfs_root, minor);
    100
    101	debugfs_create_file("fps_show", S_IRUGO | S_IWUSR, minor->debugfs_root,
    102			    minor->dev, &sti_drm_fps_fops);
    103
    104	DRM_INFO("%s: debugfs installed\n", DRIVER_NAME);
    105}
    106
    107static const struct drm_mode_config_funcs sti_mode_config_funcs = {
    108	.fb_create = drm_gem_fb_create,
    109	.atomic_check = drm_atomic_helper_check,
    110	.atomic_commit = drm_atomic_helper_commit,
    111};
    112
    113static void sti_mode_config_init(struct drm_device *dev)
    114{
    115	dev->mode_config.min_width = 0;
    116	dev->mode_config.min_height = 0;
    117
    118	/*
    119	 * set max width and height as default value.
    120	 * this value would be used to check framebuffer size limitation
    121	 * at drm_mode_addfb().
    122	 */
    123	dev->mode_config.max_width = STI_MAX_FB_WIDTH;
    124	dev->mode_config.max_height = STI_MAX_FB_HEIGHT;
    125
    126	dev->mode_config.funcs = &sti_mode_config_funcs;
    127
    128	dev->mode_config.normalize_zpos = true;
    129}
    130
    131DEFINE_DRM_GEM_CMA_FOPS(sti_driver_fops);
    132
    133static const struct drm_driver sti_driver = {
    134	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
    135	.fops = &sti_driver_fops,
    136	DRM_GEM_CMA_DRIVER_OPS,
    137
    138	.debugfs_init = sti_drm_dbg_init,
    139
    140	.name = DRIVER_NAME,
    141	.desc = DRIVER_DESC,
    142	.date = DRIVER_DATE,
    143	.major = DRIVER_MAJOR,
    144	.minor = DRIVER_MINOR,
    145};
    146
    147static int sti_init(struct drm_device *ddev)
    148{
    149	struct sti_private *private;
    150
    151	private = kzalloc(sizeof(*private), GFP_KERNEL);
    152	if (!private)
    153		return -ENOMEM;
    154
    155	ddev->dev_private = (void *)private;
    156	dev_set_drvdata(ddev->dev, ddev);
    157	private->drm_dev = ddev;
    158
    159	drm_mode_config_init(ddev);
    160
    161	sti_mode_config_init(ddev);
    162
    163	drm_kms_helper_poll_init(ddev);
    164
    165	return 0;
    166}
    167
    168static void sti_cleanup(struct drm_device *ddev)
    169{
    170	struct sti_private *private = ddev->dev_private;
    171
    172	drm_kms_helper_poll_fini(ddev);
    173	drm_atomic_helper_shutdown(ddev);
    174	drm_mode_config_cleanup(ddev);
    175	component_unbind_all(ddev->dev, ddev);
    176	kfree(private);
    177	ddev->dev_private = NULL;
    178}
    179
    180static int sti_bind(struct device *dev)
    181{
    182	struct drm_device *ddev;
    183	int ret;
    184
    185	ddev = drm_dev_alloc(&sti_driver, dev);
    186	if (IS_ERR(ddev))
    187		return PTR_ERR(ddev);
    188
    189	ret = sti_init(ddev);
    190	if (ret)
    191		goto err_drm_dev_put;
    192
    193	ret = component_bind_all(ddev->dev, ddev);
    194	if (ret)
    195		goto err_cleanup;
    196
    197	ret = drm_dev_register(ddev, 0);
    198	if (ret)
    199		goto err_cleanup;
    200
    201	drm_mode_config_reset(ddev);
    202
    203	drm_fbdev_generic_setup(ddev, 32);
    204
    205	return 0;
    206
    207err_cleanup:
    208	sti_cleanup(ddev);
    209err_drm_dev_put:
    210	drm_dev_put(ddev);
    211	return ret;
    212}
    213
    214static void sti_unbind(struct device *dev)
    215{
    216	struct drm_device *ddev = dev_get_drvdata(dev);
    217
    218	drm_dev_unregister(ddev);
    219	sti_cleanup(ddev);
    220	drm_dev_put(ddev);
    221}
    222
    223static const struct component_master_ops sti_ops = {
    224	.bind = sti_bind,
    225	.unbind = sti_unbind,
    226};
    227
    228static int sti_platform_probe(struct platform_device *pdev)
    229{
    230	struct device *dev = &pdev->dev;
    231	struct device_node *node = dev->of_node;
    232	struct device_node *child_np;
    233	struct component_match *match = NULL;
    234
    235	dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
    236
    237	devm_of_platform_populate(dev);
    238
    239	child_np = of_get_next_available_child(node, NULL);
    240
    241	while (child_np) {
    242		drm_of_component_match_add(dev, &match, component_compare_of,
    243					   child_np);
    244		child_np = of_get_next_available_child(node, child_np);
    245	}
    246
    247	return component_master_add_with_match(dev, &sti_ops, match);
    248}
    249
    250static int sti_platform_remove(struct platform_device *pdev)
    251{
    252	component_master_del(&pdev->dev, &sti_ops);
    253
    254	return 0;
    255}
    256
    257static const struct of_device_id sti_dt_ids[] = {
    258	{ .compatible = "st,sti-display-subsystem", },
    259	{ /* end node */ },
    260};
    261MODULE_DEVICE_TABLE(of, sti_dt_ids);
    262
    263static struct platform_driver sti_platform_driver = {
    264	.probe = sti_platform_probe,
    265	.remove = sti_platform_remove,
    266	.driver = {
    267		.name = DRIVER_NAME,
    268		.of_match_table = sti_dt_ids,
    269	},
    270};
    271
    272static struct platform_driver * const drivers[] = {
    273	&sti_tvout_driver,
    274	&sti_hqvdp_driver,
    275	&sti_hdmi_driver,
    276	&sti_hda_driver,
    277	&sti_dvo_driver,
    278	&sti_vtg_driver,
    279	&sti_compositor_driver,
    280	&sti_platform_driver,
    281};
    282
    283static int sti_drm_init(void)
    284{
    285	if (drm_firmware_drivers_only())
    286		return -ENODEV;
    287
    288	return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
    289}
    290module_init(sti_drm_init);
    291
    292static void sti_drm_exit(void)
    293{
    294	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
    295}
    296module_exit(sti_drm_exit);
    297
    298MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
    299MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
    300MODULE_LICENSE("GPL");