linux/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/* Hisilicon Hibmc SoC drm driver
   3 *
   4 * Based on the bochs drm driver.
   5 *
   6 * Copyright (c) 2016 Huawei Limited.
   7 *
   8 * Author:
   9 *      Rongrong Zou <zourongrong@huawei.com>
  10 *      Rongrong Zou <zourongrong@gmail.com>
  11 *      Jianhua Li <lijianhua@huawei.com>
  12 */
  13
  14#include <linux/console.h>
  15#include <linux/module.h>
  16
  17#include <drm/drm_atomic_helper.h>
  18#include <drm/drm_probe_helper.h>
  19
  20#include "hibmc_drm_drv.h"
  21#include "hibmc_drm_regs.h"
  22
  23static const struct file_operations hibmc_fops = {
  24        .owner          = THIS_MODULE,
  25        DRM_VRAM_MM_FILE_OPERATIONS
  26};
  27
  28static irqreturn_t hibmc_drm_interrupt(int irq, void *arg)
  29{
  30        struct drm_device *dev = (struct drm_device *)arg;
  31        struct hibmc_drm_private *priv =
  32                (struct hibmc_drm_private *)dev->dev_private;
  33        u32 status;
  34
  35        status = readl(priv->mmio + HIBMC_RAW_INTERRUPT);
  36
  37        if (status & HIBMC_RAW_INTERRUPT_VBLANK(1)) {
  38                writel(HIBMC_RAW_INTERRUPT_VBLANK(1),
  39                       priv->mmio + HIBMC_RAW_INTERRUPT);
  40                drm_handle_vblank(dev, 0);
  41        }
  42
  43        return IRQ_HANDLED;
  44}
  45
  46static struct drm_driver hibmc_driver = {
  47        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
  48        .fops                   = &hibmc_fops,
  49        .name                   = "hibmc",
  50        .date                   = "20160828",
  51        .desc                   = "hibmc drm driver",
  52        .major                  = 1,
  53        .minor                  = 0,
  54        .gem_free_object_unlocked =
  55                drm_gem_vram_driver_gem_free_object_unlocked,
  56        .dumb_create            = hibmc_dumb_create,
  57        .dumb_map_offset        = drm_gem_vram_driver_dumb_mmap_offset,
  58        .irq_handler            = hibmc_drm_interrupt,
  59};
  60
  61static int __maybe_unused hibmc_pm_suspend(struct device *dev)
  62{
  63        struct pci_dev *pdev = to_pci_dev(dev);
  64        struct drm_device *drm_dev = pci_get_drvdata(pdev);
  65
  66        return drm_mode_config_helper_suspend(drm_dev);
  67}
  68
  69static int  __maybe_unused hibmc_pm_resume(struct device *dev)
  70{
  71        struct pci_dev *pdev = to_pci_dev(dev);
  72        struct drm_device *drm_dev = pci_get_drvdata(pdev);
  73
  74        return drm_mode_config_helper_resume(drm_dev);
  75}
  76
  77static const struct dev_pm_ops hibmc_pm_ops = {
  78        SET_SYSTEM_SLEEP_PM_OPS(hibmc_pm_suspend,
  79                                hibmc_pm_resume)
  80};
  81
  82static int hibmc_kms_init(struct hibmc_drm_private *priv)
  83{
  84        int ret;
  85
  86        drm_mode_config_init(priv->dev);
  87        priv->mode_config_initialized = true;
  88
  89        priv->dev->mode_config.min_width = 0;
  90        priv->dev->mode_config.min_height = 0;
  91        priv->dev->mode_config.max_width = 1920;
  92        priv->dev->mode_config.max_height = 1440;
  93
  94        priv->dev->mode_config.fb_base = priv->fb_base;
  95        priv->dev->mode_config.preferred_depth = 24;
  96        priv->dev->mode_config.prefer_shadow = 0;
  97
  98        priv->dev->mode_config.funcs = (void *)&hibmc_mode_funcs;
  99
 100        ret = hibmc_de_init(priv);
 101        if (ret) {
 102                DRM_ERROR("failed to init de: %d\n", ret);
 103                return ret;
 104        }
 105
 106        ret = hibmc_vdac_init(priv);
 107        if (ret) {
 108                DRM_ERROR("failed to init vdac: %d\n", ret);
 109                return ret;
 110        }
 111
 112        return 0;
 113}
 114
 115static void hibmc_kms_fini(struct hibmc_drm_private *priv)
 116{
 117        if (priv->mode_config_initialized) {
 118                drm_mode_config_cleanup(priv->dev);
 119                priv->mode_config_initialized = false;
 120        }
 121}
 122
 123/*
 124 * It can operate in one of three modes: 0, 1 or Sleep.
 125 */
 126void hibmc_set_power_mode(struct hibmc_drm_private *priv,
 127                          unsigned int power_mode)
 128{
 129        unsigned int control_value = 0;
 130        void __iomem   *mmio = priv->mmio;
 131        unsigned int input = 1;
 132
 133        if (power_mode > HIBMC_PW_MODE_CTL_MODE_SLEEP)
 134                return;
 135
 136        if (power_mode == HIBMC_PW_MODE_CTL_MODE_SLEEP)
 137                input = 0;
 138
 139        control_value = readl(mmio + HIBMC_POWER_MODE_CTRL);
 140        control_value &= ~(HIBMC_PW_MODE_CTL_MODE_MASK |
 141                           HIBMC_PW_MODE_CTL_OSC_INPUT_MASK);
 142        control_value |= HIBMC_FIELD(HIBMC_PW_MODE_CTL_MODE, power_mode);
 143        control_value |= HIBMC_FIELD(HIBMC_PW_MODE_CTL_OSC_INPUT, input);
 144        writel(control_value, mmio + HIBMC_POWER_MODE_CTRL);
 145}
 146
 147void hibmc_set_current_gate(struct hibmc_drm_private *priv, unsigned int gate)
 148{
 149        unsigned int gate_reg;
 150        unsigned int mode;
 151        void __iomem   *mmio = priv->mmio;
 152
 153        /* Get current power mode. */
 154        mode = (readl(mmio + HIBMC_POWER_MODE_CTRL) &
 155                HIBMC_PW_MODE_CTL_MODE_MASK) >> HIBMC_PW_MODE_CTL_MODE_SHIFT;
 156
 157        switch (mode) {
 158        case HIBMC_PW_MODE_CTL_MODE_MODE0:
 159                gate_reg = HIBMC_MODE0_GATE;
 160                break;
 161
 162        case HIBMC_PW_MODE_CTL_MODE_MODE1:
 163                gate_reg = HIBMC_MODE1_GATE;
 164                break;
 165
 166        default:
 167                gate_reg = HIBMC_MODE0_GATE;
 168                break;
 169        }
 170        writel(gate, mmio + gate_reg);
 171}
 172
 173static void hibmc_hw_config(struct hibmc_drm_private *priv)
 174{
 175        unsigned int reg;
 176
 177        /* On hardware reset, power mode 0 is default. */
 178        hibmc_set_power_mode(priv, HIBMC_PW_MODE_CTL_MODE_MODE0);
 179
 180        /* Enable display power gate & LOCALMEM power gate*/
 181        reg = readl(priv->mmio + HIBMC_CURRENT_GATE);
 182        reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
 183        reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
 184        reg |= HIBMC_CURR_GATE_DISPLAY(1);
 185        reg |= HIBMC_CURR_GATE_LOCALMEM(1);
 186
 187        hibmc_set_current_gate(priv, reg);
 188
 189        /*
 190         * Reset the memory controller. If the memory controller
 191         * is not reset in chip,the system might hang when sw accesses
 192         * the memory.The memory should be resetted after
 193         * changing the MXCLK.
 194         */
 195        reg = readl(priv->mmio + HIBMC_MISC_CTRL);
 196        reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
 197        reg |= HIBMC_MSCCTL_LOCALMEM_RESET(0);
 198        writel(reg, priv->mmio + HIBMC_MISC_CTRL);
 199
 200        reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
 201        reg |= HIBMC_MSCCTL_LOCALMEM_RESET(1);
 202
 203        writel(reg, priv->mmio + HIBMC_MISC_CTRL);
 204}
 205
 206static int hibmc_hw_map(struct hibmc_drm_private *priv)
 207{
 208        struct drm_device *dev = priv->dev;
 209        struct pci_dev *pdev = dev->pdev;
 210        resource_size_t addr, size, ioaddr, iosize;
 211
 212        ioaddr = pci_resource_start(pdev, 1);
 213        iosize = pci_resource_len(pdev, 1);
 214        priv->mmio = devm_ioremap_nocache(dev->dev, ioaddr, iosize);
 215        if (!priv->mmio) {
 216                DRM_ERROR("Cannot map mmio region\n");
 217                return -ENOMEM;
 218        }
 219
 220        addr = pci_resource_start(pdev, 0);
 221        size = pci_resource_len(pdev, 0);
 222        priv->fb_map = devm_ioremap(dev->dev, addr, size);
 223        if (!priv->fb_map) {
 224                DRM_ERROR("Cannot map framebuffer\n");
 225                return -ENOMEM;
 226        }
 227        priv->fb_base = addr;
 228        priv->fb_size = size;
 229
 230        return 0;
 231}
 232
 233static int hibmc_hw_init(struct hibmc_drm_private *priv)
 234{
 235        int ret;
 236
 237        ret = hibmc_hw_map(priv);
 238        if (ret)
 239                return ret;
 240
 241        hibmc_hw_config(priv);
 242
 243        return 0;
 244}
 245
 246static int hibmc_unload(struct drm_device *dev)
 247{
 248        struct hibmc_drm_private *priv = dev->dev_private;
 249
 250        hibmc_fbdev_fini(priv);
 251
 252        drm_atomic_helper_shutdown(dev);
 253
 254        if (dev->irq_enabled)
 255                drm_irq_uninstall(dev);
 256        if (priv->msi_enabled)
 257                pci_disable_msi(dev->pdev);
 258
 259        hibmc_kms_fini(priv);
 260        hibmc_mm_fini(priv);
 261        dev->dev_private = NULL;
 262        return 0;
 263}
 264
 265static int hibmc_load(struct drm_device *dev)
 266{
 267        struct hibmc_drm_private *priv;
 268        int ret;
 269
 270        priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL);
 271        if (!priv) {
 272                DRM_ERROR("no memory to allocate for hibmc_drm_private\n");
 273                return -ENOMEM;
 274        }
 275        dev->dev_private = priv;
 276        priv->dev = dev;
 277
 278        ret = hibmc_hw_init(priv);
 279        if (ret)
 280                goto err;
 281
 282        ret = hibmc_mm_init(priv);
 283        if (ret)
 284                goto err;
 285
 286        ret = hibmc_kms_init(priv);
 287        if (ret)
 288                goto err;
 289
 290        ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
 291        if (ret) {
 292                DRM_ERROR("failed to initialize vblank: %d\n", ret);
 293                goto err;
 294        }
 295
 296        priv->msi_enabled = 0;
 297        ret = pci_enable_msi(dev->pdev);
 298        if (ret) {
 299                DRM_WARN("enabling MSI failed: %d\n", ret);
 300        } else {
 301                priv->msi_enabled = 1;
 302                ret = drm_irq_install(dev, dev->pdev->irq);
 303                if (ret)
 304                        DRM_WARN("install irq failed: %d\n", ret);
 305        }
 306
 307        /* reset all the states of crtc/plane/encoder/connector */
 308        drm_mode_config_reset(dev);
 309
 310        ret = hibmc_fbdev_init(priv);
 311        if (ret) {
 312                DRM_ERROR("failed to initialize fbdev: %d\n", ret);
 313                goto err;
 314        }
 315
 316        return 0;
 317
 318err:
 319        hibmc_unload(dev);
 320        DRM_ERROR("failed to initialize drm driver: %d\n", ret);
 321        return ret;
 322}
 323
 324static int hibmc_pci_probe(struct pci_dev *pdev,
 325                           const struct pci_device_id *ent)
 326{
 327        struct drm_device *dev;
 328        int ret;
 329
 330        dev = drm_dev_alloc(&hibmc_driver, &pdev->dev);
 331        if (IS_ERR(dev)) {
 332                DRM_ERROR("failed to allocate drm_device\n");
 333                return PTR_ERR(dev);
 334        }
 335
 336        dev->pdev = pdev;
 337        pci_set_drvdata(pdev, dev);
 338
 339        ret = pci_enable_device(pdev);
 340        if (ret) {
 341                DRM_ERROR("failed to enable pci device: %d\n", ret);
 342                goto err_free;
 343        }
 344
 345        ret = hibmc_load(dev);
 346        if (ret) {
 347                DRM_ERROR("failed to load hibmc: %d\n", ret);
 348                goto err_disable;
 349        }
 350
 351        ret = drm_dev_register(dev, 0);
 352        if (ret) {
 353                DRM_ERROR("failed to register drv for userspace access: %d\n",
 354                          ret);
 355                goto err_unload;
 356        }
 357        return 0;
 358
 359err_unload:
 360        hibmc_unload(dev);
 361err_disable:
 362        pci_disable_device(pdev);
 363err_free:
 364        drm_dev_put(dev);
 365
 366        return ret;
 367}
 368
 369static void hibmc_pci_remove(struct pci_dev *pdev)
 370{
 371        struct drm_device *dev = pci_get_drvdata(pdev);
 372
 373        drm_dev_unregister(dev);
 374        hibmc_unload(dev);
 375        drm_dev_put(dev);
 376}
 377
 378static struct pci_device_id hibmc_pci_table[] = {
 379        { PCI_VDEVICE(HUAWEI, 0x1711) },
 380        {0,}
 381};
 382
 383static struct pci_driver hibmc_pci_driver = {
 384        .name =         "hibmc-drm",
 385        .id_table =     hibmc_pci_table,
 386        .probe =        hibmc_pci_probe,
 387        .remove =       hibmc_pci_remove,
 388        .driver.pm =    &hibmc_pm_ops,
 389};
 390
 391static int __init hibmc_init(void)
 392{
 393        return pci_register_driver(&hibmc_pci_driver);
 394}
 395
 396static void __exit hibmc_exit(void)
 397{
 398        return pci_unregister_driver(&hibmc_pci_driver);
 399}
 400
 401module_init(hibmc_init);
 402module_exit(hibmc_exit);
 403
 404MODULE_DEVICE_TABLE(pci, hibmc_pci_table);
 405MODULE_AUTHOR("RongrongZou <zourongrong@huawei.com>");
 406MODULE_DESCRIPTION("DRM Driver for Hisilicon Hibmc");
 407MODULE_LICENSE("GPL v2");
 408