| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* Hisilicon Hibmc SoC drm driver |
|---|
| 2 | 3 | * |
|---|
| 3 | 4 | * Based on the bochs drm driver. |
|---|
| .. | .. |
|---|
| 8 | 9 | * Rongrong Zou <zourongrong@huawei.com> |
|---|
| 9 | 10 | * Rongrong Zou <zourongrong@gmail.com> |
|---|
| 10 | 11 | * Jianhua Li <lijianhua@huawei.com> |
|---|
| 11 | | - * |
|---|
| 12 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 13 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 14 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 15 | | - * (at your option) any later version. |
|---|
| 16 | | - * |
|---|
| 17 | 12 | */ |
|---|
| 18 | 13 | |
|---|
| 19 | | -#include <linux/console.h> |
|---|
| 20 | 14 | #include <linux/module.h> |
|---|
| 15 | +#include <linux/pci.h> |
|---|
| 21 | 16 | |
|---|
| 22 | 17 | #include <drm/drm_atomic_helper.h> |
|---|
| 23 | | -#include <drm/drm_crtc_helper.h> |
|---|
| 18 | +#include <drm/drm_drv.h> |
|---|
| 19 | +#include <drm/drm_gem_vram_helper.h> |
|---|
| 20 | +#include <drm/drm_irq.h> |
|---|
| 21 | +#include <drm/drm_managed.h> |
|---|
| 22 | +#include <drm/drm_vblank.h> |
|---|
| 24 | 23 | |
|---|
| 25 | 24 | #include "hibmc_drm_drv.h" |
|---|
| 26 | 25 | #include "hibmc_drm_regs.h" |
|---|
| 27 | 26 | |
|---|
| 28 | | -static const struct file_operations hibmc_fops = { |
|---|
| 29 | | - .owner = THIS_MODULE, |
|---|
| 30 | | - .open = drm_open, |
|---|
| 31 | | - .release = drm_release, |
|---|
| 32 | | - .unlocked_ioctl = drm_ioctl, |
|---|
| 33 | | - .compat_ioctl = drm_compat_ioctl, |
|---|
| 34 | | - .mmap = hibmc_mmap, |
|---|
| 35 | | - .poll = drm_poll, |
|---|
| 36 | | - .read = drm_read, |
|---|
| 37 | | - .llseek = no_llseek, |
|---|
| 38 | | -}; |
|---|
| 27 | +DEFINE_DRM_GEM_FOPS(hibmc_fops); |
|---|
| 39 | 28 | |
|---|
| 40 | | -irqreturn_t hibmc_drm_interrupt(int irq, void *arg) |
|---|
| 29 | +static irqreturn_t hibmc_drm_interrupt(int irq, void *arg) |
|---|
| 41 | 30 | { |
|---|
| 42 | 31 | struct drm_device *dev = (struct drm_device *)arg; |
|---|
| 43 | 32 | struct hibmc_drm_private *priv = |
|---|
| .. | .. |
|---|
| 56 | 45 | } |
|---|
| 57 | 46 | |
|---|
| 58 | 47 | static struct drm_driver hibmc_driver = { |
|---|
| 59 | | - .driver_features = DRIVER_GEM | DRIVER_MODESET | |
|---|
| 60 | | - DRIVER_ATOMIC | DRIVER_HAVE_IRQ, |
|---|
| 48 | + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, |
|---|
| 61 | 49 | .fops = &hibmc_fops, |
|---|
| 62 | 50 | .name = "hibmc", |
|---|
| 63 | 51 | .date = "20160828", |
|---|
| 64 | 52 | .desc = "hibmc drm driver", |
|---|
| 65 | 53 | .major = 1, |
|---|
| 66 | 54 | .minor = 0, |
|---|
| 67 | | - .gem_free_object_unlocked = hibmc_gem_free_object, |
|---|
| 55 | + .debugfs_init = drm_vram_mm_debugfs_init, |
|---|
| 68 | 56 | .dumb_create = hibmc_dumb_create, |
|---|
| 69 | | - .dumb_map_offset = hibmc_dumb_mmap_offset, |
|---|
| 57 | + .dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset, |
|---|
| 58 | + .gem_prime_mmap = drm_gem_prime_mmap, |
|---|
| 70 | 59 | .irq_handler = hibmc_drm_interrupt, |
|---|
| 71 | 60 | }; |
|---|
| 72 | 61 | |
|---|
| 73 | 62 | static int __maybe_unused hibmc_pm_suspend(struct device *dev) |
|---|
| 74 | 63 | { |
|---|
| 75 | | - struct pci_dev *pdev = to_pci_dev(dev); |
|---|
| 76 | | - struct drm_device *drm_dev = pci_get_drvdata(pdev); |
|---|
| 77 | | - struct hibmc_drm_private *priv = drm_dev->dev_private; |
|---|
| 64 | + struct drm_device *drm_dev = dev_get_drvdata(dev); |
|---|
| 78 | 65 | |
|---|
| 79 | | - drm_kms_helper_poll_disable(drm_dev); |
|---|
| 80 | | - priv->suspend_state = drm_atomic_helper_suspend(drm_dev); |
|---|
| 81 | | - if (IS_ERR(priv->suspend_state)) { |
|---|
| 82 | | - DRM_ERROR("drm_atomic_helper_suspend failed: %ld\n", |
|---|
| 83 | | - PTR_ERR(priv->suspend_state)); |
|---|
| 84 | | - drm_kms_helper_poll_enable(drm_dev); |
|---|
| 85 | | - return PTR_ERR(priv->suspend_state); |
|---|
| 86 | | - } |
|---|
| 87 | | - |
|---|
| 88 | | - return 0; |
|---|
| 66 | + return drm_mode_config_helper_suspend(drm_dev); |
|---|
| 89 | 67 | } |
|---|
| 90 | 68 | |
|---|
| 91 | 69 | static int __maybe_unused hibmc_pm_resume(struct device *dev) |
|---|
| 92 | 70 | { |
|---|
| 93 | | - struct pci_dev *pdev = to_pci_dev(dev); |
|---|
| 94 | | - struct drm_device *drm_dev = pci_get_drvdata(pdev); |
|---|
| 95 | | - struct hibmc_drm_private *priv = drm_dev->dev_private; |
|---|
| 71 | + struct drm_device *drm_dev = dev_get_drvdata(dev); |
|---|
| 96 | 72 | |
|---|
| 97 | | - drm_atomic_helper_resume(drm_dev, priv->suspend_state); |
|---|
| 98 | | - drm_kms_helper_poll_enable(drm_dev); |
|---|
| 99 | | - |
|---|
| 100 | | - return 0; |
|---|
| 73 | + return drm_mode_config_helper_resume(drm_dev); |
|---|
| 101 | 74 | } |
|---|
| 102 | 75 | |
|---|
| 103 | 76 | static const struct dev_pm_ops hibmc_pm_ops = { |
|---|
| .. | .. |
|---|
| 115 | 88 | priv->dev->mode_config.min_width = 0; |
|---|
| 116 | 89 | priv->dev->mode_config.min_height = 0; |
|---|
| 117 | 90 | priv->dev->mode_config.max_width = 1920; |
|---|
| 118 | | - priv->dev->mode_config.max_height = 1440; |
|---|
| 91 | + priv->dev->mode_config.max_height = 1200; |
|---|
| 119 | 92 | |
|---|
| 120 | 93 | priv->dev->mode_config.fb_base = priv->fb_base; |
|---|
| 121 | | - priv->dev->mode_config.preferred_depth = 24; |
|---|
| 122 | | - priv->dev->mode_config.prefer_shadow = 0; |
|---|
| 94 | + priv->dev->mode_config.preferred_depth = 32; |
|---|
| 95 | + priv->dev->mode_config.prefer_shadow = 1; |
|---|
| 123 | 96 | |
|---|
| 124 | 97 | priv->dev->mode_config.funcs = (void *)&hibmc_mode_funcs; |
|---|
| 125 | 98 | |
|---|
| 126 | 99 | ret = hibmc_de_init(priv); |
|---|
| 127 | 100 | if (ret) { |
|---|
| 128 | | - DRM_ERROR("failed to init de: %d\n", ret); |
|---|
| 101 | + drm_err(priv->dev, "failed to init de: %d\n", ret); |
|---|
| 129 | 102 | return ret; |
|---|
| 130 | 103 | } |
|---|
| 131 | 104 | |
|---|
| 132 | 105 | ret = hibmc_vdac_init(priv); |
|---|
| 133 | 106 | if (ret) { |
|---|
| 134 | | - DRM_ERROR("failed to init vdac: %d\n", ret); |
|---|
| 107 | + drm_err(priv->dev, "failed to init vdac: %d\n", ret); |
|---|
| 135 | 108 | return ret; |
|---|
| 136 | 109 | } |
|---|
| 137 | 110 | |
|---|
| .. | .. |
|---|
| 237 | 210 | |
|---|
| 238 | 211 | ioaddr = pci_resource_start(pdev, 1); |
|---|
| 239 | 212 | iosize = pci_resource_len(pdev, 1); |
|---|
| 240 | | - priv->mmio = devm_ioremap_nocache(dev->dev, ioaddr, iosize); |
|---|
| 213 | + priv->mmio = devm_ioremap(dev->dev, ioaddr, iosize); |
|---|
| 241 | 214 | if (!priv->mmio) { |
|---|
| 242 | | - DRM_ERROR("Cannot map mmio region\n"); |
|---|
| 215 | + drm_err(dev, "Cannot map mmio region\n"); |
|---|
| 243 | 216 | return -ENOMEM; |
|---|
| 244 | 217 | } |
|---|
| 245 | 218 | |
|---|
| .. | .. |
|---|
| 247 | 220 | size = pci_resource_len(pdev, 0); |
|---|
| 248 | 221 | priv->fb_map = devm_ioremap(dev->dev, addr, size); |
|---|
| 249 | 222 | if (!priv->fb_map) { |
|---|
| 250 | | - DRM_ERROR("Cannot map framebuffer\n"); |
|---|
| 223 | + drm_err(dev, "Cannot map framebuffer\n"); |
|---|
| 251 | 224 | return -ENOMEM; |
|---|
| 252 | 225 | } |
|---|
| 253 | 226 | priv->fb_base = addr; |
|---|
| .. | .. |
|---|
| 273 | 246 | { |
|---|
| 274 | 247 | struct hibmc_drm_private *priv = dev->dev_private; |
|---|
| 275 | 248 | |
|---|
| 276 | | - hibmc_fbdev_fini(priv); |
|---|
| 277 | | - |
|---|
| 278 | 249 | drm_atomic_helper_shutdown(dev); |
|---|
| 279 | 250 | |
|---|
| 280 | 251 | if (dev->irq_enabled) |
|---|
| 281 | 252 | drm_irq_uninstall(dev); |
|---|
| 282 | | - if (priv->msi_enabled) |
|---|
| 283 | | - pci_disable_msi(dev->pdev); |
|---|
| 284 | 253 | |
|---|
| 254 | + pci_disable_msi(dev->pdev); |
|---|
| 285 | 255 | hibmc_kms_fini(priv); |
|---|
| 286 | 256 | hibmc_mm_fini(priv); |
|---|
| 287 | 257 | dev->dev_private = NULL; |
|---|
| .. | .. |
|---|
| 293 | 263 | struct hibmc_drm_private *priv; |
|---|
| 294 | 264 | int ret; |
|---|
| 295 | 265 | |
|---|
| 296 | | - priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL); |
|---|
| 266 | + priv = drmm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |
|---|
| 297 | 267 | if (!priv) { |
|---|
| 298 | | - DRM_ERROR("no memory to allocate for hibmc_drm_private\n"); |
|---|
| 268 | + drm_err(dev, "no memory to allocate for hibmc_drm_private\n"); |
|---|
| 299 | 269 | return -ENOMEM; |
|---|
| 300 | 270 | } |
|---|
| 301 | 271 | dev->dev_private = priv; |
|---|
| .. | .. |
|---|
| 315 | 285 | |
|---|
| 316 | 286 | ret = drm_vblank_init(dev, dev->mode_config.num_crtc); |
|---|
| 317 | 287 | if (ret) { |
|---|
| 318 | | - DRM_ERROR("failed to initialize vblank: %d\n", ret); |
|---|
| 288 | + drm_err(dev, "failed to initialize vblank: %d\n", ret); |
|---|
| 319 | 289 | goto err; |
|---|
| 320 | 290 | } |
|---|
| 321 | 291 | |
|---|
| 322 | | - priv->msi_enabled = 0; |
|---|
| 323 | 292 | ret = pci_enable_msi(dev->pdev); |
|---|
| 324 | 293 | if (ret) { |
|---|
| 325 | | - DRM_WARN("enabling MSI failed: %d\n", ret); |
|---|
| 294 | + drm_warn(dev, "enabling MSI failed: %d\n", ret); |
|---|
| 326 | 295 | } else { |
|---|
| 327 | | - priv->msi_enabled = 1; |
|---|
| 328 | 296 | ret = drm_irq_install(dev, dev->pdev->irq); |
|---|
| 329 | 297 | if (ret) |
|---|
| 330 | | - DRM_WARN("install irq failed: %d\n", ret); |
|---|
| 298 | + drm_warn(dev, "install irq failed: %d\n", ret); |
|---|
| 331 | 299 | } |
|---|
| 332 | 300 | |
|---|
| 333 | 301 | /* reset all the states of crtc/plane/encoder/connector */ |
|---|
| 334 | 302 | drm_mode_config_reset(dev); |
|---|
| 335 | 303 | |
|---|
| 336 | | - ret = hibmc_fbdev_init(priv); |
|---|
| 337 | | - if (ret) { |
|---|
| 338 | | - DRM_ERROR("failed to initialize fbdev: %d\n", ret); |
|---|
| 339 | | - goto err; |
|---|
| 340 | | - } |
|---|
| 341 | | - |
|---|
| 342 | 304 | return 0; |
|---|
| 343 | 305 | |
|---|
| 344 | 306 | err: |
|---|
| 345 | 307 | hibmc_unload(dev); |
|---|
| 346 | | - DRM_ERROR("failed to initialize drm driver: %d\n", ret); |
|---|
| 308 | + drm_err(dev, "failed to initialize drm driver: %d\n", ret); |
|---|
| 347 | 309 | return ret; |
|---|
| 348 | 310 | } |
|---|
| 349 | 311 | |
|---|
| .. | .. |
|---|
| 352 | 314 | { |
|---|
| 353 | 315 | struct drm_device *dev; |
|---|
| 354 | 316 | int ret; |
|---|
| 317 | + |
|---|
| 318 | + ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, |
|---|
| 319 | + "hibmcdrmfb"); |
|---|
| 320 | + if (ret) |
|---|
| 321 | + return ret; |
|---|
| 355 | 322 | |
|---|
| 356 | 323 | dev = drm_dev_alloc(&hibmc_driver, &pdev->dev); |
|---|
| 357 | 324 | if (IS_ERR(dev)) { |
|---|
| .. | .. |
|---|
| 364 | 331 | |
|---|
| 365 | 332 | ret = pci_enable_device(pdev); |
|---|
| 366 | 333 | if (ret) { |
|---|
| 367 | | - DRM_ERROR("failed to enable pci device: %d\n", ret); |
|---|
| 334 | + drm_err(dev, "failed to enable pci device: %d\n", ret); |
|---|
| 368 | 335 | goto err_free; |
|---|
| 369 | 336 | } |
|---|
| 370 | 337 | |
|---|
| 371 | 338 | ret = hibmc_load(dev); |
|---|
| 372 | 339 | if (ret) { |
|---|
| 373 | | - DRM_ERROR("failed to load hibmc: %d\n", ret); |
|---|
| 340 | + drm_err(dev, "failed to load hibmc: %d\n", ret); |
|---|
| 374 | 341 | goto err_disable; |
|---|
| 375 | 342 | } |
|---|
| 376 | 343 | |
|---|
| 377 | 344 | ret = drm_dev_register(dev, 0); |
|---|
| 378 | 345 | if (ret) { |
|---|
| 379 | | - DRM_ERROR("failed to register drv for userspace access: %d\n", |
|---|
| 346 | + drm_err(dev, "failed to register drv for userspace access: %d\n", |
|---|
| 380 | 347 | ret); |
|---|
| 381 | 348 | goto err_unload; |
|---|
| 382 | 349 | } |
|---|
| 350 | + |
|---|
| 351 | + drm_fbdev_generic_setup(dev, dev->mode_config.preferred_depth); |
|---|
| 352 | + |
|---|
| 383 | 353 | return 0; |
|---|
| 384 | 354 | |
|---|
| 385 | 355 | err_unload: |
|---|
| .. | .. |
|---|
| 387 | 357 | err_disable: |
|---|
| 388 | 358 | pci_disable_device(pdev); |
|---|
| 389 | 359 | err_free: |
|---|
| 390 | | - drm_dev_unref(dev); |
|---|
| 360 | + drm_dev_put(dev); |
|---|
| 391 | 361 | |
|---|
| 392 | 362 | return ret; |
|---|
| 393 | 363 | } |
|---|
| .. | .. |
|---|
| 398 | 368 | |
|---|
| 399 | 369 | drm_dev_unregister(dev); |
|---|
| 400 | 370 | hibmc_unload(dev); |
|---|
| 401 | | - drm_dev_unref(dev); |
|---|
| 402 | 371 | } |
|---|
| 403 | 372 | |
|---|
| 404 | 373 | static struct pci_device_id hibmc_pci_table[] = { |
|---|
| 405 | | - {0x19e5, 0x1711, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
|---|
| 374 | + { PCI_VDEVICE(HUAWEI, 0x1711) }, |
|---|
| 406 | 375 | {0,} |
|---|
| 407 | 376 | }; |
|---|
| 408 | 377 | |
|---|
| .. | .. |
|---|
| 414 | 383 | .driver.pm = &hibmc_pm_ops, |
|---|
| 415 | 384 | }; |
|---|
| 416 | 385 | |
|---|
| 417 | | -static int __init hibmc_init(void) |
|---|
| 418 | | -{ |
|---|
| 419 | | - return pci_register_driver(&hibmc_pci_driver); |
|---|
| 420 | | -} |
|---|
| 421 | | - |
|---|
| 422 | | -static void __exit hibmc_exit(void) |
|---|
| 423 | | -{ |
|---|
| 424 | | - return pci_unregister_driver(&hibmc_pci_driver); |
|---|
| 425 | | -} |
|---|
| 426 | | - |
|---|
| 427 | | -module_init(hibmc_init); |
|---|
| 428 | | -module_exit(hibmc_exit); |
|---|
| 386 | +module_pci_driver(hibmc_pci_driver); |
|---|
| 429 | 387 | |
|---|
| 430 | 388 | MODULE_DEVICE_TABLE(pci, hibmc_pci_table); |
|---|
| 431 | 389 | MODULE_AUTHOR("RongrongZou <zourongrong@huawei.com>"); |
|---|