diff options
Diffstat (limited to 'drivers/gpu/drm/msm/msm_kms.c')
-rw-r--r-- | drivers/gpu/drm/msm/msm_kms.c | 59 |
1 files changed, 43 insertions, 16 deletions
diff --git a/drivers/gpu/drm/msm/msm_kms.c b/drivers/gpu/drm/msm/msm_kms.c index 35d5397e73b4..6889f1c1e721 100644 --- a/drivers/gpu/drm/msm/msm_kms.c +++ b/drivers/gpu/drm/msm/msm_kms.c @@ -13,6 +13,7 @@ #include <drm/drm_drv.h> #include <drm/drm_mode_config.h> #include <drm/drm_vblank.h> +#include <drm/clients/drm_client_setup.h> #include "disp/msm_disp_snapshot.h" #include "msm_drv.h" @@ -137,7 +138,7 @@ static int vblank_ctrl_queue_work(struct msm_drm_private *priv, vbl_work->enable = enable; vbl_work->priv = priv; - queue_work(priv->wq, &vbl_work->work); + queue_work(priv->kms->wq, &vbl_work->work); return 0; } @@ -176,9 +177,9 @@ static int msm_kms_fault_handler(void *arg, unsigned long iova, int flags, void return -ENOSYS; } -struct msm_gem_address_space *msm_kms_init_aspace(struct drm_device *dev) +struct drm_gpuvm *msm_kms_init_vm(struct drm_device *dev) { - struct msm_gem_address_space *aspace; + struct drm_gpuvm *vm; struct msm_mmu *mmu; struct device *mdp_dev = dev->dev; struct device *mdss_dev = mdp_dev->parent; @@ -204,17 +205,26 @@ struct msm_gem_address_space *msm_kms_init_aspace(struct drm_device *dev) return NULL; } - aspace = msm_gem_address_space_create(mmu, "mdp_kms", - 0x1000, 0x100000000 - 0x1000); - if (IS_ERR(aspace)) { - dev_err(mdp_dev, "aspace create, error %pe\n", aspace); + vm = msm_gem_vm_create(dev, mmu, "mdp_kms", + 0x1000, 0x100000000 - 0x1000, true); + if (IS_ERR(vm)) { + dev_err(mdp_dev, "vm create, error %pe\n", vm); mmu->funcs->destroy(mmu); - return aspace; + return vm; } - msm_mmu_set_fault_handler(aspace->mmu, kms, msm_kms_fault_handler); + msm_mmu_set_fault_handler(to_msm_vm(vm)->mmu, kms, msm_kms_fault_handler); - return aspace; + return vm; +} + +void msm_drm_kms_unregister(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct msm_drm_private *priv = platform_get_drvdata(pdev); + struct drm_device *ddev = priv->dev; + + drm_atomic_helper_shutdown(ddev); } void msm_drm_kms_uninit(struct device *dev) @@ -227,10 +237,17 @@ void msm_drm_kms_uninit(struct device *dev) BUG_ON(!kms); + /* We must cancel and cleanup any pending vblank enable/disable + * work before msm_irq_uninstall() to avoid work re-enabling an + * irq after uninstall has disabled it. + */ + + flush_workqueue(kms->wq); + /* clean up event worker threads */ - for (i = 0; i < priv->num_crtcs; i++) { - if (priv->event_thread[i].worker) - kthread_destroy_worker(priv->event_thread[i].worker); + for (i = 0; i < MAX_CRTCS; i++) { + if (kms->event_thread[i].worker) + kthread_destroy_worker(kms->event_thread[i].worker); } drm_kms_helper_poll_fini(ddev); @@ -261,7 +278,7 @@ int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv) ret = priv->kms_init(ddev); if (ret) { DRM_DEV_ERROR(dev, "failed to load kms\n"); - return ret; + goto err_msm_uninit; } /* Enable normalization of plane zpos */ @@ -283,7 +300,7 @@ int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv) struct msm_drm_thread *ev_thread; /* initialize event thread */ - ev_thread = &priv->event_thread[drm_crtc_index(crtc)]; + ev_thread = &kms->event_thread[drm_crtc_index(crtc)]; ev_thread->dev = ddev; ev_thread->worker = kthread_run_worker(0, "crtc_event:%d", crtc->base.id); if (IS_ERR(ev_thread->worker)) { @@ -296,7 +313,7 @@ int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv) sched_set_fifo(ev_thread->worker->task); } - ret = drm_vblank_init(ddev, priv->num_crtcs); + ret = drm_vblank_init(ddev, ddev->mode_config.num_crtc); if (ret < 0) { DRM_DEV_ERROR(dev, "failed to initialize vblank\n"); goto err_msm_uninit; @@ -359,3 +376,13 @@ void msm_kms_shutdown(struct platform_device *pdev) if (drm && drm->registered && priv->kms) drm_atomic_helper_shutdown(drm); } + +void msm_drm_kms_post_init(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct msm_drm_private *priv = platform_get_drvdata(pdev); + struct drm_device *ddev = priv->dev; + + drm_kms_helper_poll_init(ddev); + drm_client_setup(ddev, NULL); +} |