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

dcss-kms.c (4236B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright 2019 NXP.
      4 */
      5
      6#include <drm/drm_atomic.h>
      7#include <drm/drm_atomic_helper.h>
      8#include <drm/drm_bridge_connector.h>
      9#include <drm/drm_drv.h>
     10#include <drm/drm_fb_helper.h>
     11#include <drm/drm_gem_cma_helper.h>
     12#include <drm/drm_gem_framebuffer_helper.h>
     13#include <drm/drm_of.h>
     14#include <drm/drm_probe_helper.h>
     15#include <drm/drm_vblank.h>
     16
     17#include "dcss-dev.h"
     18#include "dcss-kms.h"
     19
     20DEFINE_DRM_GEM_CMA_FOPS(dcss_cma_fops);
     21
     22static const struct drm_mode_config_funcs dcss_drm_mode_config_funcs = {
     23	.fb_create = drm_gem_fb_create,
     24	.output_poll_changed = drm_fb_helper_output_poll_changed,
     25	.atomic_check = drm_atomic_helper_check,
     26	.atomic_commit = drm_atomic_helper_commit,
     27};
     28
     29static const struct drm_driver dcss_kms_driver = {
     30	.driver_features	= DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
     31	DRM_GEM_CMA_DRIVER_OPS,
     32	.fops			= &dcss_cma_fops,
     33	.name			= "imx-dcss",
     34	.desc			= "i.MX8MQ Display Subsystem",
     35	.date			= "20190917",
     36	.major			= 1,
     37	.minor			= 0,
     38	.patchlevel		= 0,
     39};
     40
     41static const struct drm_mode_config_helper_funcs dcss_mode_config_helpers = {
     42	.atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
     43};
     44
     45static void dcss_kms_mode_config_init(struct dcss_kms_dev *kms)
     46{
     47	struct drm_mode_config *config = &kms->base.mode_config;
     48
     49	drm_mode_config_init(&kms->base);
     50
     51	config->min_width = 1;
     52	config->min_height = 1;
     53	config->max_width = 4096;
     54	config->max_height = 4096;
     55	config->normalize_zpos = true;
     56
     57	config->funcs = &dcss_drm_mode_config_funcs;
     58	config->helper_private = &dcss_mode_config_helpers;
     59}
     60
     61static const struct drm_encoder_funcs dcss_kms_simple_encoder_funcs = {
     62	.destroy = drm_encoder_cleanup,
     63};
     64
     65static int dcss_kms_bridge_connector_init(struct dcss_kms_dev *kms)
     66{
     67	struct drm_device *ddev = &kms->base;
     68	struct drm_encoder *encoder = &kms->encoder;
     69	struct drm_crtc *crtc = (struct drm_crtc *)&kms->crtc;
     70	struct drm_panel *panel;
     71	struct drm_bridge *bridge;
     72	int ret;
     73
     74	ret = drm_of_find_panel_or_bridge(ddev->dev->of_node, 0, 0,
     75					  &panel, &bridge);
     76	if (ret)
     77		return ret;
     78
     79	if (!bridge) {
     80		dev_err(ddev->dev, "No bridge found %d.\n", ret);
     81		return -ENODEV;
     82	}
     83
     84	encoder->possible_crtcs = drm_crtc_mask(crtc);
     85
     86	ret = drm_encoder_init(&kms->base, encoder,
     87			       &dcss_kms_simple_encoder_funcs,
     88			       DRM_MODE_ENCODER_NONE, NULL);
     89	if (ret) {
     90		dev_err(ddev->dev, "Failed initializing encoder %d.\n", ret);
     91		return ret;
     92	}
     93
     94	ret = drm_bridge_attach(encoder, bridge, NULL,
     95				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
     96	if (ret < 0)
     97		return ret;
     98
     99	kms->connector = drm_bridge_connector_init(ddev, encoder);
    100	if (IS_ERR(kms->connector)) {
    101		dev_err(ddev->dev, "Unable to create bridge connector.\n");
    102		return PTR_ERR(kms->connector);
    103	}
    104
    105	drm_connector_attach_encoder(kms->connector, encoder);
    106
    107	return 0;
    108}
    109
    110struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss)
    111{
    112	struct dcss_kms_dev *kms;
    113	struct drm_device *drm;
    114	struct dcss_crtc *crtc;
    115	int ret;
    116
    117	kms = devm_drm_dev_alloc(dcss->dev, &dcss_kms_driver,
    118				 struct dcss_kms_dev, base);
    119	if (IS_ERR(kms))
    120		return kms;
    121
    122	drm = &kms->base;
    123	crtc = &kms->crtc;
    124
    125	drm->dev_private = dcss;
    126
    127	dcss_kms_mode_config_init(kms);
    128
    129	ret = drm_vblank_init(drm, 1);
    130	if (ret)
    131		goto cleanup_mode_config;
    132
    133	ret = dcss_kms_bridge_connector_init(kms);
    134	if (ret)
    135		goto cleanup_mode_config;
    136
    137	ret = dcss_crtc_init(crtc, drm);
    138	if (ret)
    139		goto cleanup_mode_config;
    140
    141	drm_mode_config_reset(drm);
    142
    143	drm_kms_helper_poll_init(drm);
    144
    145	drm_bridge_connector_enable_hpd(kms->connector);
    146
    147	ret = drm_dev_register(drm, 0);
    148	if (ret)
    149		goto cleanup_crtc;
    150
    151	drm_fbdev_generic_setup(drm, 32);
    152
    153	return kms;
    154
    155cleanup_crtc:
    156	drm_bridge_connector_disable_hpd(kms->connector);
    157	drm_kms_helper_poll_fini(drm);
    158	dcss_crtc_deinit(crtc, drm);
    159
    160cleanup_mode_config:
    161	drm_mode_config_cleanup(drm);
    162	drm->dev_private = NULL;
    163
    164	return ERR_PTR(ret);
    165}
    166
    167void dcss_kms_detach(struct dcss_kms_dev *kms)
    168{
    169	struct drm_device *drm = &kms->base;
    170
    171	drm_dev_unregister(drm);
    172	drm_bridge_connector_disable_hpd(kms->connector);
    173	drm_kms_helper_poll_fini(drm);
    174	drm_atomic_helper_shutdown(drm);
    175	drm_crtc_vblank_off(&kms->crtc.base);
    176	drm_mode_config_cleanup(drm);
    177	dcss_crtc_deinit(&kms->crtc, drm);
    178	drm->dev_private = NULL;
    179}