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