static int imx_drm_bind(struct device *dev)
{
struct drm_device *drm;
+ struct imx_drm_device *imxdrm;
int ret;
drm = drm_dev_alloc(&imx_drm_driver, dev);
if (IS_ERR(drm))
return PTR_ERR(drm);
+ imxdrm = devm_kzalloc(dev, sizeof(*imxdrm), GFP_KERNEL);
+ if (!imxdrm) {
+ ret = -ENOMEM;
+ goto err_unref;
+ }
+
+ imxdrm->drm = drm;
+ drm->dev_private = imxdrm;
+
+ imxdrm->wq = alloc_ordered_workqueue("imxdrm", 0);
+ if (!imxdrm->wq) {
+ ret = -ENOMEM;
+ goto err_unref;
+ }
+
+ init_waitqueue_head(&imxdrm->commit.wait);
+
/*
* enable drm irq mode.
* - with irq_enabled = true, we can use the vblank feature.
component_unbind_all(drm->dev, drm);
err_kms:
drm_mode_config_cleanup(drm);
+
+ destroy_workqueue(imxdrm->wq);
+
+err_unref:
drm_dev_put(drm);
return ret;
static void imx_drm_unbind(struct device *dev)
{
struct drm_device *drm = dev_get_drvdata(dev);
+ struct imx_drm_device *imxdrm = drm->dev_private;
+
+ flush_workqueue(imxdrm->wq);
drm_dev_unregister(drm);
component_unbind_all(drm->dev, drm);
dev_set_drvdata(dev, NULL);
+ destroy_workqueue(imxdrm->wq);
+
drm_dev_put(drm);
}
unsigned int pipes;
struct drm_fbdev_cma *fbhelper;
struct drm_atomic_state *state;
+
+ struct workqueue_struct *wq;
+ struct {
+ wait_queue_head_t wait;
+ bool pending;
+ } commit;
};
struct imx_crtc_state {