Lines Matching +full:sc7180 +full:- +full:dpu

1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2016-2018, 2020-2021 The Linux Foundation. All rights reserved.
8 #include <linux/dma-mapping.h>
32 * - 1.0.0 - initial interface
33 * - 1.1.0 - adds madvise, and support for submits with > 4 cmd buffers
34 * - 1.2.0 - adds explicit fence support for submit ioctl
35 * - 1.3.0 - adds GMEM_BASE + NR_RINGS params, SUBMITQUEUE_NEW +
38 * - 1.4.0 - softpin, MSM_RELOC_BO_DUMP, and GEM_INFO support to set/get
40 * - 1.5.0 - Add SUBMITQUERY_QUERY ioctl
41 * - 1.6.0 - Syncobj support
42 * - 1.7.0 - Add MSM_PARAM_SUSPENDS to access suspend count
43 * - 1.8.0 - Add MSM_BO_CACHED_COHERENT for supported GPUs (a6xx)
112 clk = devm_clk_get(&pdev->dev, name); in msm_clk_get()
113 if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER) in msm_clk_get()
118 clk = devm_clk_get(&pdev->dev, name2); in msm_clk_get()
120 dev_warn(&pdev->dev, "Using legacy clk name binding. Use " in msm_clk_get()
140 DRM_DEV_ERROR(&pdev->dev, "failed to get memory resource: %s\n", name); in _msm_ioremap()
141 return ERR_PTR(-EINVAL); in _msm_ioremap()
146 ptr = devm_ioremap(&pdev->dev, res->start, size); in _msm_ioremap()
149 DRM_DEV_ERROR(&pdev->dev, "failed to ioremap: %s\n", name); in _msm_ioremap()
150 return ERR_PTR(-ENOMEM); in _msm_ioremap()
206 struct msm_drm_private *priv = dev->dev_private; in msm_irq()
207 struct msm_kms *kms = priv->kms; in msm_irq()
211 return kms->funcs->irq(kms); in msm_irq()
216 struct msm_drm_private *priv = dev->dev_private; in msm_irq_preinstall()
217 struct msm_kms *kms = priv->kms; in msm_irq_preinstall()
221 kms->funcs->irq_preinstall(kms); in msm_irq_preinstall()
226 struct msm_drm_private *priv = dev->dev_private; in msm_irq_postinstall()
227 struct msm_kms *kms = priv->kms; in msm_irq_postinstall()
231 if (kms->funcs->irq_postinstall) in msm_irq_postinstall()
232 return kms->funcs->irq_postinstall(kms); in msm_irq_postinstall()
242 return -ENOTCONN; in msm_irq_install()
246 ret = request_irq(irq, msm_irq, 0, dev->driver->name, dev); in msm_irq_install()
261 struct msm_drm_private *priv = dev->dev_private; in msm_irq_uninstall()
262 struct msm_kms *kms = priv->kms; in msm_irq_uninstall()
264 kms->funcs->irq_uninstall(kms); in msm_irq_uninstall()
265 free_irq(kms->irq, dev); in msm_irq_uninstall()
279 struct msm_drm_private *priv = vbl_work->priv; in vblank_ctrl_worker()
280 struct msm_kms *kms = priv->kms; in vblank_ctrl_worker()
282 if (vbl_work->enable) in vblank_ctrl_worker()
283 kms->funcs->enable_vblank(kms, priv->crtcs[vbl_work->crtc_id]); in vblank_ctrl_worker()
285 kms->funcs->disable_vblank(kms, priv->crtcs[vbl_work->crtc_id]); in vblank_ctrl_worker()
297 return -ENOMEM; in vblank_ctrl_queue_work()
299 INIT_WORK(&vbl_work->work, vblank_ctrl_worker); in vblank_ctrl_queue_work()
301 vbl_work->crtc_id = crtc_id; in vblank_ctrl_queue_work()
302 vbl_work->enable = enable; in vblank_ctrl_queue_work()
303 vbl_work->priv = priv; in vblank_ctrl_queue_work()
305 queue_work(priv->wq, &vbl_work->work); in vblank_ctrl_queue_work()
314 struct msm_drm_private *priv = ddev->dev_private; in msm_drm_uninit()
315 struct msm_kms *kms = priv->kms; in msm_drm_uninit()
316 struct msm_mdss *mdss = priv->mdss; in msm_drm_uninit()
323 * msm_drm_init, drm_dev->registered is used as an indicator that the in msm_drm_uninit()
326 if (ddev->registered) { in msm_drm_uninit()
332 * work before msm_irq_uninstall() to avoid work re-enabling an in msm_drm_uninit()
336 flush_workqueue(priv->wq); in msm_drm_uninit()
339 for (i = 0; i < priv->num_crtcs; i++) { in msm_drm_uninit()
340 if (priv->event_thread[i].worker) in msm_drm_uninit()
341 kthread_destroy_worker(priv->event_thread[i].worker); in msm_drm_uninit()
352 if (fbdev && priv->fbdev) in msm_drm_uninit()
364 if (kms && kms->funcs) in msm_drm_uninit()
365 kms->funcs->destroy(kms); in msm_drm_uninit()
367 if (priv->vram.paddr) { in msm_drm_uninit()
369 drm_mm_takedown(&priv->vram.mm); in msm_drm_uninit()
370 dma_free_attrs(dev, priv->vram.size, NULL, in msm_drm_uninit()
371 priv->vram.paddr, attrs); in msm_drm_uninit()
376 if (mdss && mdss->funcs) in msm_drm_uninit()
377 mdss->funcs->destroy(ddev); in msm_drm_uninit()
379 ddev->dev_private = NULL; in msm_drm_uninit()
382 destroy_workqueue(priv->wq); in msm_drm_uninit()
394 struct device *dev = &pdev->dev; in get_mdp_ver()
403 struct msm_drm_private *priv = dev->dev_private; in msm_use_mmu()
406 return priv->is_a2xx || iommu_present(&platform_bus_type); in msm_use_mmu()
411 struct msm_drm_private *priv = dev->dev_private; in msm_init_vram()
416 /* In the device-tree world, we could have a 'memory-region' in msm_init_vram()
433 node = of_parse_phandle(dev->dev->of_node, "memory-region", 0); in msm_init_vram()
440 size = r.end - r.start; in msm_init_vram()
445 * mach-msm: in msm_init_vram()
456 priv->vram.size = size; in msm_init_vram()
458 drm_mm_init(&priv->vram.mm, 0, (size >> PAGE_SHIFT) - 1); in msm_init_vram()
459 spin_lock_init(&priv->vram.lock); in msm_init_vram()
464 /* note that for no-kernel-mapping, the vaddr returned in msm_init_vram()
465 * is bogus, but non-null if allocation succeeded: in msm_init_vram()
467 p = dma_alloc_attrs(dev->dev, size, in msm_init_vram()
468 &priv->vram.paddr, GFP_KERNEL, attrs); in msm_init_vram()
470 DRM_DEV_ERROR(dev->dev, "failed to allocate VRAM\n"); in msm_init_vram()
471 priv->vram.paddr = 0; in msm_init_vram()
472 return -ENOMEM; in msm_init_vram()
475 DRM_DEV_INFO(dev->dev, "VRAM: %08x->%08x\n", in msm_init_vram()
476 (uint32_t)priv->vram.paddr, in msm_init_vram()
477 (uint32_t)(priv->vram.paddr + size)); in msm_init_vram()
502 ret = -ENOMEM; in msm_drm_init()
506 ddev->dev_private = priv; in msm_drm_init()
507 priv->dev = ddev; in msm_drm_init()
523 mdss = priv->mdss; in msm_drm_init()
525 priv->wq = alloc_ordered_workqueue("msm", 0); in msm_drm_init()
526 priv->hangcheck_period = DRM_MSM_HANGCHECK_DEFAULT_PERIOD; in msm_drm_init()
528 INIT_LIST_HEAD(&priv->objects); in msm_drm_init()
529 mutex_init(&priv->obj_lock); in msm_drm_init()
531 INIT_LIST_HEAD(&priv->inactive_willneed); in msm_drm_init()
532 INIT_LIST_HEAD(&priv->inactive_dontneed); in msm_drm_init()
533 INIT_LIST_HEAD(&priv->inactive_unpinned); in msm_drm_init()
534 mutex_init(&priv->mm_lock); in msm_drm_init()
538 might_lock(&priv->mm_lock); in msm_drm_init()
547 /* Bind all our sub-components: */ in msm_drm_init()
559 priv->kms = kms; in msm_drm_init()
566 priv->kms = kms; in msm_drm_init()
570 WARN_ON(dev->of_node); in msm_drm_init()
578 priv->kms = NULL; in msm_drm_init()
583 ddev->mode_config.normalize_zpos = true; in msm_drm_init()
586 kms->dev = ddev; in msm_drm_init()
587 ret = kms->funcs->hw_init(kms); in msm_drm_init()
594 ddev->mode_config.funcs = &mode_config_funcs; in msm_drm_init()
595 ddev->mode_config.helper_private = &mode_config_helper_funcs; in msm_drm_init()
597 for (i = 0; i < priv->num_crtcs; i++) { in msm_drm_init()
599 priv->event_thread[i].crtc_id = priv->crtcs[i]->base.id; in msm_drm_init()
600 priv->event_thread[i].dev = ddev; in msm_drm_init()
601 priv->event_thread[i].worker = kthread_create_worker(0, in msm_drm_init()
602 "crtc_event:%d", priv->event_thread[i].crtc_id); in msm_drm_init()
603 if (IS_ERR(priv->event_thread[i].worker)) { in msm_drm_init()
604 ret = PTR_ERR(priv->event_thread[i].worker); in msm_drm_init()
606 ret = PTR_ERR(priv->event_thread[i].worker); in msm_drm_init()
610 sched_set_fifo(priv->event_thread[i].worker->task); in msm_drm_init()
613 ret = drm_vblank_init(ddev, priv->num_crtcs); in msm_drm_init()
621 ret = msm_irq_install(ddev, kms->irq); in msm_drm_init()
642 priv->fbdev = msm_fbdev_init(ddev); in msm_drm_init()
657 if (mdss && mdss->funcs) in msm_drm_init()
658 mdss->funcs->destroy(ddev); in msm_drm_init()
674 struct msm_drm_private *priv = dev->dev_private; in load_gpu()
678 if (!priv->gpu) in load_gpu()
679 priv->gpu = adreno_load_gpu(dev); in load_gpu()
687 struct msm_drm_private *priv = dev->dev_private; in context_init()
692 return -ENOMEM; in context_init()
694 INIT_LIST_HEAD(&ctx->submitqueues); in context_init()
695 rwlock_init(&ctx->queuelock); in context_init()
697 kref_init(&ctx->ref); in context_init()
700 ctx->aspace = msm_gpu_create_private_address_space(priv->gpu, current); in context_init()
701 file->driver_priv = ctx; in context_init()
703 ctx->seqno = atomic_inc_return(&ident); in context_init()
726 struct msm_drm_private *priv = dev->dev_private; in msm_postclose()
727 struct msm_file_private *ctx = file->driver_priv; in msm_postclose()
729 mutex_lock(&dev->struct_mutex); in msm_postclose()
730 if (ctx == priv->lastctx) in msm_postclose()
731 priv->lastctx = NULL; in msm_postclose()
732 mutex_unlock(&dev->struct_mutex); in msm_postclose()
739 struct drm_device *dev = crtc->dev; in msm_crtc_enable_vblank()
740 unsigned int pipe = crtc->index; in msm_crtc_enable_vblank()
741 struct msm_drm_private *priv = dev->dev_private; in msm_crtc_enable_vblank()
742 struct msm_kms *kms = priv->kms; in msm_crtc_enable_vblank()
744 return -ENXIO; in msm_crtc_enable_vblank()
751 struct drm_device *dev = crtc->dev; in msm_crtc_disable_vblank()
752 unsigned int pipe = crtc->index; in msm_crtc_disable_vblank()
753 struct msm_drm_private *priv = dev->dev_private; in msm_crtc_disable_vblank()
754 struct msm_kms *kms = priv->kms; in msm_crtc_disable_vblank()
768 struct msm_drm_private *priv = dev->dev_private; in msm_ioctl_get_param()
775 if (args->pipe != MSM_PIPE_3D0) in msm_ioctl_get_param()
776 return -EINVAL; in msm_ioctl_get_param()
778 gpu = priv->gpu; in msm_ioctl_get_param()
781 return -ENXIO; in msm_ioctl_get_param()
783 return gpu->funcs->get_param(gpu, args->param, &args->value); in msm_ioctl_get_param()
791 if (args->flags & ~MSM_BO_FLAGS) { in msm_ioctl_gem_new()
792 DRM_ERROR("invalid flags: %08x\n", args->flags); in msm_ioctl_gem_new()
793 return -EINVAL; in msm_ioctl_gem_new()
796 return msm_gem_new_handle(dev, file, args->size, in msm_ioctl_gem_new()
797 args->flags, &args->handle, NULL); in msm_ioctl_gem_new()
810 ktime_t timeout = to_ktime(args->timeout); in msm_ioctl_gem_cpu_prep()
813 if (args->op & ~MSM_PREP_FLAGS) { in msm_ioctl_gem_cpu_prep()
814 DRM_ERROR("invalid op: %08x\n", args->op); in msm_ioctl_gem_cpu_prep()
815 return -EINVAL; in msm_ioctl_gem_cpu_prep()
818 obj = drm_gem_object_lookup(file, args->handle); in msm_ioctl_gem_cpu_prep()
820 return -ENOENT; in msm_ioctl_gem_cpu_prep()
822 ret = msm_gem_cpu_prep(obj, args->op, &timeout); in msm_ioctl_gem_cpu_prep()
836 obj = drm_gem_object_lookup(file, args->handle); in msm_ioctl_gem_cpu_fini()
838 return -ENOENT; in msm_ioctl_gem_cpu_fini()
851 struct msm_drm_private *priv = dev->dev_private; in msm_ioctl_gem_info_iova()
852 struct msm_file_private *ctx = file->driver_priv; in msm_ioctl_gem_info_iova()
854 if (!priv->gpu) in msm_ioctl_gem_info_iova()
855 return -EINVAL; in msm_ioctl_gem_info_iova()
858 * Don't pin the memory here - just get an address so that userspace can in msm_ioctl_gem_info_iova()
861 return msm_gem_get_iova(obj, ctx->aspace, iova); in msm_ioctl_gem_info_iova()
872 if (args->pad) in msm_ioctl_gem_info()
873 return -EINVAL; in msm_ioctl_gem_info()
875 switch (args->info) { in msm_ioctl_gem_info()
879 if (args->len) in msm_ioctl_gem_info()
880 return -EINVAL; in msm_ioctl_gem_info()
886 return -EINVAL; in msm_ioctl_gem_info()
889 obj = drm_gem_object_lookup(file, args->handle); in msm_ioctl_gem_info()
891 return -ENOENT; in msm_ioctl_gem_info()
895 switch (args->info) { in msm_ioctl_gem_info()
897 args->value = msm_gem_mmap_offset(obj); in msm_ioctl_gem_info()
900 ret = msm_ioctl_gem_info_iova(dev, file, obj, &args->value); in msm_ioctl_gem_info()
904 if (args->len >= sizeof(msm_obj->name)) { in msm_ioctl_gem_info()
905 ret = -EINVAL; in msm_ioctl_gem_info()
908 if (copy_from_user(msm_obj->name, u64_to_user_ptr(args->value), in msm_ioctl_gem_info()
909 args->len)) { in msm_ioctl_gem_info()
910 msm_obj->name[0] = '\0'; in msm_ioctl_gem_info()
911 ret = -EFAULT; in msm_ioctl_gem_info()
914 msm_obj->name[args->len] = '\0'; in msm_ioctl_gem_info()
915 for (i = 0; i < args->len; i++) { in msm_ioctl_gem_info()
916 if (!isprint(msm_obj->name[i])) { in msm_ioctl_gem_info()
917 msm_obj->name[i] = '\0'; in msm_ioctl_gem_info()
923 if (args->value && (args->len < strlen(msm_obj->name))) { in msm_ioctl_gem_info()
924 ret = -EINVAL; in msm_ioctl_gem_info()
927 args->len = strlen(msm_obj->name); in msm_ioctl_gem_info()
928 if (args->value) { in msm_ioctl_gem_info()
929 if (copy_to_user(u64_to_user_ptr(args->value), in msm_ioctl_gem_info()
930 msm_obj->name, args->len)) in msm_ioctl_gem_info()
931 ret = -EFAULT; in msm_ioctl_gem_info()
944 struct msm_drm_private *priv = dev->dev_private; in msm_ioctl_wait_fence()
946 ktime_t timeout = to_ktime(args->timeout); in msm_ioctl_wait_fence()
948 struct msm_gpu *gpu = priv->gpu; in msm_ioctl_wait_fence()
952 if (args->pad) { in msm_ioctl_wait_fence()
953 DRM_ERROR("invalid pad: %08x\n", args->pad); in msm_ioctl_wait_fence()
954 return -EINVAL; in msm_ioctl_wait_fence()
960 queue = msm_submitqueue_get(file->driver_priv, args->queueid); in msm_ioctl_wait_fence()
962 return -ENOENT; in msm_ioctl_wait_fence()
966 * back to underlying dma-fence in msm_ioctl_wait_fence()
972 ret = mutex_lock_interruptible(&queue->lock); in msm_ioctl_wait_fence()
975 fence = idr_find(&queue->fence_idr, args->fence); in msm_ioctl_wait_fence()
978 mutex_unlock(&queue->lock); in msm_ioctl_wait_fence()
985 ret = -ETIMEDOUT; in msm_ioctl_wait_fence()
986 } else if (ret != -ERESTARTSYS) { in msm_ioctl_wait_fence()
1003 switch (args->madv) { in msm_ioctl_gem_madvise()
1008 return -EINVAL; in msm_ioctl_gem_madvise()
1011 obj = drm_gem_object_lookup(file, args->handle); in msm_ioctl_gem_madvise()
1013 return -ENOENT; in msm_ioctl_gem_madvise()
1016 ret = msm_gem_madvise(obj, args->madv); in msm_ioctl_gem_madvise()
1018 args->retained = ret; in msm_ioctl_gem_madvise()
1033 if (args->flags & ~MSM_SUBMITQUEUE_FLAGS) in msm_ioctl_submitqueue_new()
1034 return -EINVAL; in msm_ioctl_submitqueue_new()
1036 return msm_submitqueue_create(dev, file->driver_priv, args->prio, in msm_ioctl_submitqueue_new()
1037 args->flags, &args->id); in msm_ioctl_submitqueue_new()
1043 return msm_submitqueue_query(dev, file->driver_priv, data); in msm_ioctl_submitqueue_query()
1051 return msm_submitqueue_remove(file->driver_priv, id); in msm_ioctl_submitqueue_close()
1102 struct msm_drm_private *priv = ddev->dev_private; in msm_runtime_suspend()
1103 struct msm_mdss *mdss = priv->mdss; in msm_runtime_suspend()
1107 if (mdss && mdss->funcs) in msm_runtime_suspend()
1108 return mdss->funcs->disable(mdss); in msm_runtime_suspend()
1116 struct msm_drm_private *priv = ddev->dev_private; in msm_runtime_resume()
1117 struct msm_mdss *mdss = priv->mdss; in msm_runtime_resume()
1121 if (mdss && mdss->funcs) in msm_runtime_resume()
1122 return mdss->funcs->enable(mdss); in msm_runtime_resume()
1147 struct msm_drm_private *priv = ddev ? ddev->dev_private : NULL; in msm_pm_prepare()
1149 if (!priv || !priv->kms) in msm_pm_prepare()
1158 struct msm_drm_private *priv = ddev ? ddev->dev_private : NULL; in msm_pm_complete()
1160 if (!priv || !priv->kms) in msm_pm_complete()
1183 return dev->of_node == data; in compare_of()
1187 * Identify what components need to be added by parsing what remote-endpoints
1195 struct device_node *np = mdp_dev->of_node; in add_components_mdp()
1210 master_dev = mdp_dev->parent; in add_components_mdp()
1226 * remote-endpoint isn't a component that we need to add in add_components_mdp()
1260 struct device *dev = &pdev->dev; in add_display_components()
1264 * MDP5/DPU based devices don't have a flat hierarchy. There is a top in add_display_components()
1265 * level parent: MDSS, and children: MDP5/DPU, DSI, HDMI, eDP etc. in add_display_components()
1266 * Populate the children devices, find the MDP5/DPU node, and then add in add_display_components()
1272 ret = of_platform_populate(dev->of_node, NULL, NULL, dev); in add_display_components()
1282 return -ENODEV; in add_display_components()
1289 mdp_dev->of_node); in add_display_components()
1311 { .compatible = "qcom,adreno-3xx" },
1313 { .compatible = "qcom,kgsl-3d0" },
1364 ret = add_gpu_components(&pdev->dev, &match); in msm_pdev_probe()
1371 ret = dma_set_mask_and_coherent(&pdev->dev, ~0); in msm_pdev_probe()
1375 ret = component_master_add_with_match(&pdev->dev, &msm_drm_ops, match); in msm_pdev_probe()
1382 of_platform_depopulate(&pdev->dev); in msm_pdev_probe()
1388 component_master_del(&pdev->dev, &msm_drm_ops); in msm_pdev_remove()
1389 of_platform_depopulate(&pdev->dev); in msm_pdev_remove()
1397 struct msm_drm_private *priv = drm ? drm->dev_private : NULL; in msm_pdev_shutdown()
1399 if (!priv || !priv->kms) in msm_pdev_shutdown()
1408 { .compatible = "qcom,sdm845-mdss", .data = (void *)KMS_DPU },
1409 { .compatible = "qcom,sc7180-mdss", .data = (void *)KMS_DPU },
1410 { .compatible = "qcom,sc7280-mdss", .data = (void *)KMS_DPU },
1411 { .compatible = "qcom,sm8150-mdss", .data = (void *)KMS_DPU },
1412 { .compatible = "qcom,sm8250-mdss", .data = (void *)KMS_DPU },
1431 return -EINVAL; in msm_drm_register()