diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 5b2f60b0e9048d..91e9ba6ea05c75 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -71,6 +71,9 @@ static int vc4_get_param_ioctl(struct drm_device *dev, void *data, if (args->pad != 0) return -EINVAL; + if (!vc4->v3d) + return -ENODEV; + switch (args->param) { case DRM_VC4_PARAM_V3D_IDENT0: ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev); @@ -271,6 +274,7 @@ static int vc4_drm_bind(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct drm_device *drm; struct vc4_dev *vc4; + struct device_node *node; int ret = 0; dev->coherent_dma_mask = DMA_BIT_MASK(32); @@ -279,6 +283,12 @@ static int vc4_drm_bind(struct device *dev) if (!vc4) return -ENOMEM; + /* If VC4 V3D is missing, don't advertise render nodes. */ + node = of_find_matching_node_and_match(NULL, vc4_v3d_dt_match, NULL); + if (!node || !of_device_is_available(node)) + vc4_drm_driver.driver_features &= ~DRIVER_RENDER; + of_node_put(node); + drm = drm_dev_alloc(&vc4_drm_driver, dev); if (IS_ERR(drm)) return PTR_ERR(drm); diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 67553b440d2082..7956f6ed9b6a0b 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -787,6 +787,7 @@ void vc4_plane_async_set_fb(struct drm_plane *plane, /* vc4_v3d.c */ extern struct platform_driver vc4_v3d_driver; +extern const struct of_device_id vc4_v3d_dt_match[]; int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused); int vc4_v3d_debugfs_regs(struct seq_file *m, void *unused); int vc4_v3d_get_bin_slot(struct vc4_dev *vc4); diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 928718b467bd22..895fa087fb3278 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -74,6 +74,11 @@ vc4_get_hang_state_ioctl(struct drm_device *dev, void *data, u32 i; int ret = 0; + if (!vc4->v3d) { + DRM_DEBUG("VC4_GET_HANG_STATE with no VC4 V3D probed\n"); + return -ENODEV; + } + spin_lock_irqsave(&vc4->job_lock, irqflags); kernel_state = vc4->hang_state; if (!kernel_state) { @@ -1124,6 +1129,11 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data, struct dma_fence *in_fence; int ret = 0; + if (!vc4->v3d) { + DRM_DEBUG("VC4_SUBMIT_CL with no VC4 V3D probed\n"); + return -ENODEV; + } + if ((args->flags & ~(VC4_SUBMIT_CL_USE_CLEAR_COLOR | VC4_SUBMIT_CL_FIXED_RCL_ORDER | VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X | diff --git a/drivers/gpu/drm/vc4/vc4_irq.c b/drivers/gpu/drm/vc4/vc4_irq.c index 4cd2ccfe15f49b..ffd0a4388752ea 100644 --- a/drivers/gpu/drm/vc4/vc4_irq.c +++ b/drivers/gpu/drm/vc4/vc4_irq.c @@ -229,6 +229,9 @@ vc4_irq_preinstall(struct drm_device *dev) { struct vc4_dev *vc4 = to_vc4_dev(dev); + if (!vc4->v3d) + return; + init_waitqueue_head(&vc4->job_wait_queue); INIT_WORK(&vc4->overflow_mem_work, vc4_overflow_mem_work); @@ -243,6 +246,9 @@ vc4_irq_postinstall(struct drm_device *dev) { struct vc4_dev *vc4 = to_vc4_dev(dev); + if (!vc4->v3d) + return 0; + /* Enable both the render done and out of memory interrupts. */ V3D_WRITE(V3D_INTENA, V3D_DRIVER_IRQS); @@ -254,6 +260,9 @@ vc4_irq_uninstall(struct drm_device *dev) { struct vc4_dev *vc4 = to_vc4_dev(dev); + if (!vc4->v3d) + return; + /* Disable sending interrupts for our driver's IRQs. */ V3D_WRITE(V3D_INTDIS, V3D_DRIVER_IRQS); diff --git a/drivers/gpu/drm/vc4/vc4_perfmon.c b/drivers/gpu/drm/vc4/vc4_perfmon.c index 437e7a27f21d91..de3cd9f71fa6f8 100644 --- a/drivers/gpu/drm/vc4/vc4_perfmon.c +++ b/drivers/gpu/drm/vc4/vc4_perfmon.c @@ -100,12 +100,18 @@ void vc4_perfmon_close_file(struct vc4_file *vc4file) int vc4_perfmon_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { + struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_file *vc4file = file_priv->driver_priv; struct drm_vc4_perfmon_create *req = data; struct vc4_perfmon *perfmon; unsigned int i; int ret; + if (!vc4->v3d) { + DRM_DEBUG("Creating perfmon no VC4 V3D probed\n"); + return -ENODEV; + } + /* Number of monitored counters cannot exceed HW limits. */ if (req->ncounters > DRM_VC4_MAX_PERF_COUNTERS || !req->ncounters) @@ -146,10 +152,16 @@ int vc4_perfmon_create_ioctl(struct drm_device *dev, void *data, int vc4_perfmon_destroy_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { + struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_file *vc4file = file_priv->driver_priv; struct drm_vc4_perfmon_destroy *req = data; struct vc4_perfmon *perfmon; + if (!vc4->v3d) { + DRM_DEBUG("Destroying perfmon no VC4 V3D probed\n"); + return -ENODEV; + } + mutex_lock(&vc4file->perfmon.lock); perfmon = idr_remove(&vc4file->perfmon.idr, req->id); mutex_unlock(&vc4file->perfmon.lock); @@ -164,11 +176,17 @@ int vc4_perfmon_destroy_ioctl(struct drm_device *dev, void *data, int vc4_perfmon_get_values_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { + struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_file *vc4file = file_priv->driver_priv; struct drm_vc4_perfmon_get_values *req = data; struct vc4_perfmon *perfmon; int ret; + if (!vc4->v3d) { + DRM_DEBUG("Getting perfmon no VC4 V3D probed\n"); + return -ENODEV; + } + mutex_lock(&vc4file->perfmon.lock); perfmon = idr_find(&vc4file->perfmon.idr, req->id); vc4_perfmon_get(perfmon); diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c index e47e29426078bf..3966889f1f415b 100644 --- a/drivers/gpu/drm/vc4/vc4_v3d.c +++ b/drivers/gpu/drm/vc4/vc4_v3d.c @@ -452,7 +452,7 @@ static int vc4_v3d_dev_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id vc4_v3d_dt_match[] = { +const struct of_device_id vc4_v3d_dt_match[] = { { .compatible = "brcm,bcm2835-v3d" }, { .compatible = "brcm,cygnus-v3d" }, { .compatible = "brcm,vc4-v3d" },