linux/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Hisilicon Kirin SoCs drm master driver
   4 *
   5 * Copyright (c) 2016 Linaro Limited.
   6 * Copyright (c) 2014-2016 Hisilicon Limited.
   7 *
   8 * Author:
   9 *      Xinliang Liu <z.liuxinliang@hisilicon.com>
  10 *      Xinliang Liu <xinliang.liu@linaro.org>
  11 *      Xinwei Kong <kong.kongxinwei@hisilicon.com>
  12 */
  13
  14#include <linux/of_platform.h>
  15#include <linux/component.h>
  16#include <linux/of_graph.h>
  17
  18#include <drm/drmP.h>
  19#include <drm/drm_atomic_helper.h>
  20#include <drm/drm_fb_cma_helper.h>
  21#include <drm/drm_fb_helper.h>
  22#include <drm/drm_gem_cma_helper.h>
  23#include <drm/drm_gem_framebuffer_helper.h>
  24#include <drm/drm_of.h>
  25#include <drm/drm_probe_helper.h>
  26
  27#include "kirin_drm_drv.h"
  28
  29static struct kirin_dc_ops *dc_ops;
  30
  31static int kirin_drm_kms_cleanup(struct drm_device *dev)
  32{
  33        drm_kms_helper_poll_fini(dev);
  34        dc_ops->cleanup(to_platform_device(dev->dev));
  35        drm_mode_config_cleanup(dev);
  36
  37        return 0;
  38}
  39
  40static const struct drm_mode_config_funcs kirin_drm_mode_config_funcs = {
  41        .fb_create = drm_gem_fb_create,
  42        .atomic_check = drm_atomic_helper_check,
  43        .atomic_commit = drm_atomic_helper_commit,
  44};
  45
  46static void kirin_drm_mode_config_init(struct drm_device *dev)
  47{
  48        dev->mode_config.min_width = 0;
  49        dev->mode_config.min_height = 0;
  50
  51        dev->mode_config.max_width = 2048;
  52        dev->mode_config.max_height = 2048;
  53
  54        dev->mode_config.funcs = &kirin_drm_mode_config_funcs;
  55}
  56
  57static int kirin_drm_kms_init(struct drm_device *dev)
  58{
  59        int ret;
  60
  61        dev_set_drvdata(dev->dev, dev);
  62
  63        /* dev->mode_config initialization */
  64        drm_mode_config_init(dev);
  65        kirin_drm_mode_config_init(dev);
  66
  67        /* display controller init */
  68        ret = dc_ops->init(to_platform_device(dev->dev));
  69        if (ret)
  70                goto err_mode_config_cleanup;
  71
  72        /* bind and init sub drivers */
  73        ret = component_bind_all(dev->dev, dev);
  74        if (ret) {
  75                DRM_ERROR("failed to bind all component.\n");
  76                goto err_dc_cleanup;
  77        }
  78
  79        /* vblank init */
  80        ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
  81        if (ret) {
  82                DRM_ERROR("failed to initialize vblank.\n");
  83                goto err_unbind_all;
  84        }
  85        /* with irq_enabled = true, we can use the vblank feature. */
  86        dev->irq_enabled = true;
  87
  88        /* reset all the states of crtc/plane/encoder/connector */
  89        drm_mode_config_reset(dev);
  90
  91        /* init kms poll for handling hpd */
  92        drm_kms_helper_poll_init(dev);
  93
  94        return 0;
  95
  96err_unbind_all:
  97        component_unbind_all(dev->dev, dev);
  98err_dc_cleanup:
  99        dc_ops->cleanup(to_platform_device(dev->dev));
 100err_mode_config_cleanup:
 101        drm_mode_config_cleanup(dev);
 102
 103        return ret;
 104}
 105
 106DEFINE_DRM_GEM_CMA_FOPS(kirin_drm_fops);
 107
 108static int kirin_gem_cma_dumb_create(struct drm_file *file,
 109                                     struct drm_device *dev,
 110                                     struct drm_mode_create_dumb *args)
 111{
 112        return drm_gem_cma_dumb_create_internal(file, dev, args);
 113}
 114
 115static struct drm_driver kirin_drm_driver = {
 116        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
 117                                  DRIVER_ATOMIC,
 118        .fops                   = &kirin_drm_fops,
 119
 120        .gem_free_object_unlocked = drm_gem_cma_free_object,
 121        .gem_vm_ops             = &drm_gem_cma_vm_ops,
 122        .dumb_create            = kirin_gem_cma_dumb_create,
 123
 124        .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
 125        .prime_fd_to_handle     = drm_gem_prime_fd_to_handle,
 126        .gem_prime_export       = drm_gem_prime_export,
 127        .gem_prime_import       = drm_gem_prime_import,
 128        .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
 129        .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
 130        .gem_prime_vmap         = drm_gem_cma_prime_vmap,
 131        .gem_prime_vunmap       = drm_gem_cma_prime_vunmap,
 132        .gem_prime_mmap         = drm_gem_cma_prime_mmap,
 133
 134        .name                   = "kirin",
 135        .desc                   = "Hisilicon Kirin SoCs' DRM Driver",
 136        .date                   = "20150718",
 137        .major                  = 1,
 138        .minor                  = 0,
 139};
 140
 141static int compare_of(struct device *dev, void *data)
 142{
 143        return dev->of_node == data;
 144}
 145
 146static int kirin_drm_bind(struct device *dev)
 147{
 148        struct drm_driver *driver = &kirin_drm_driver;
 149        struct drm_device *drm_dev;
 150        int ret;
 151
 152        drm_dev = drm_dev_alloc(driver, dev);
 153        if (IS_ERR(drm_dev))
 154                return PTR_ERR(drm_dev);
 155
 156        ret = kirin_drm_kms_init(drm_dev);
 157        if (ret)
 158                goto err_drm_dev_put;
 159
 160        ret = drm_dev_register(drm_dev, 0);
 161        if (ret)
 162                goto err_kms_cleanup;
 163
 164        drm_fbdev_generic_setup(drm_dev, 32);
 165
 166        return 0;
 167
 168err_kms_cleanup:
 169        kirin_drm_kms_cleanup(drm_dev);
 170err_drm_dev_put:
 171        drm_dev_put(drm_dev);
 172
 173        return ret;
 174}
 175
 176static void kirin_drm_unbind(struct device *dev)
 177{
 178        struct drm_device *drm_dev = dev_get_drvdata(dev);
 179
 180        drm_dev_unregister(drm_dev);
 181        kirin_drm_kms_cleanup(drm_dev);
 182        drm_dev_put(drm_dev);
 183}
 184
 185static const struct component_master_ops kirin_drm_ops = {
 186        .bind = kirin_drm_bind,
 187        .unbind = kirin_drm_unbind,
 188};
 189
 190static int kirin_drm_platform_probe(struct platform_device *pdev)
 191{
 192        struct device *dev = &pdev->dev;
 193        struct device_node *np = dev->of_node;
 194        struct component_match *match = NULL;
 195        struct device_node *remote;
 196
 197        dc_ops = (struct kirin_dc_ops *)of_device_get_match_data(dev);
 198        if (!dc_ops) {
 199                DRM_ERROR("failed to get dt id data\n");
 200                return -EINVAL;
 201        }
 202
 203        remote = of_graph_get_remote_node(np, 0, 0);
 204        if (!remote)
 205                return -ENODEV;
 206
 207        drm_of_component_match_add(dev, &match, compare_of, remote);
 208        of_node_put(remote);
 209
 210        return component_master_add_with_match(dev, &kirin_drm_ops, match);
 211
 212        return 0;
 213}
 214
 215static int kirin_drm_platform_remove(struct platform_device *pdev)
 216{
 217        component_master_del(&pdev->dev, &kirin_drm_ops);
 218        dc_ops = NULL;
 219        return 0;
 220}
 221
 222static const struct of_device_id kirin_drm_dt_ids[] = {
 223        { .compatible = "hisilicon,hi6220-ade",
 224          .data = &ade_dc_ops,
 225        },
 226        { /* end node */ },
 227};
 228MODULE_DEVICE_TABLE(of, kirin_drm_dt_ids);
 229
 230static struct platform_driver kirin_drm_platform_driver = {
 231        .probe = kirin_drm_platform_probe,
 232        .remove = kirin_drm_platform_remove,
 233        .driver = {
 234                .name = "kirin-drm",
 235                .of_match_table = kirin_drm_dt_ids,
 236        },
 237};
 238
 239module_platform_driver(kirin_drm_platform_driver);
 240
 241MODULE_AUTHOR("Xinliang Liu <xinliang.liu@linaro.org>");
 242MODULE_AUTHOR("Xinliang Liu <z.liuxinliang@hisilicon.com>");
 243MODULE_AUTHOR("Xinwei Kong <kong.kongxinwei@hisilicon.com>");
 244MODULE_DESCRIPTION("hisilicon Kirin SoCs' DRM master driver");
 245MODULE_LICENSE("GPL v2");
 246