staticbool separate_gpu_kms;
MODULE_PARM_DESC(separate_gpu_drm, "Use separate DRM device for the GPU (0=single DRM device for both GPU and display (default), 1=two DRM devices)");
module_param(separate_gpu_kms, bool, 0400);
if (priv->kms_init) {
ret = drmm_mode_config_init(ddev); if (ret) goto err_put_dev;
}
dma_set_max_seg_size(dev, UINT_MAX);
/* Bind all our sub-components: */ if (gpu_ops)
ret = gpu_ops->bind(dev, dev, NULL); else
ret = component_bind_all(dev, ddev); if (ret) goto err_put_dev;
ret = msm_gem_shrinker_init(ddev); if (ret) goto err_msm_uninit;
if (priv->kms_init) {
ret = msm_drm_kms_init(dev, drv); if (ret) goto err_msm_uninit;
}
ret = drm_dev_register(ddev, 0); if (ret) goto err_msm_uninit;
ret = msm_debugfs_late_init(ddev); if (ret) goto err_msm_uninit;
staticint msm_open(struct drm_device *dev, struct drm_file *file)
{ /* For now, load gpu on open.. to avoid the requirement of having *firmwareintheinitrd.
*/
load_gpu(dev);
/* for now, we just have 3d pipe.. eventually this would need to *bemoreclevertodispatchtoappropriategpumodule:
*/ if ((args->pipe != MSM_PIPE_3D0) || (args->pad != 0)) return -EINVAL;
if (msm_context_is_vmbind(ctx)) return UERR(EINVAL, dev, "VM_BIND is enabled");
/* Only supported if per-process address space is supported: */ if (priv->gpu->vm == vm) return UERR(EOPNOTSUPP, dev, "requires per-process pgtables");
if (should_fail(&fail_gem_iova, obj->size)) return -ENOMEM;
/* Impose a moderate upper bound on metadata size: */ if (metadata_size > 128) { return -EOVERFLOW;
}
/* Use a temporary buf to keep copy_from_user() outside of gem obj lock: */
buf = memdup_user(metadata, metadata_size); if (IS_ERR(buf)) return PTR_ERR(buf);
ret = msm_gem_lock_interruptible(obj); if (ret) goto out;
new_metadata =
krealloc(msm_obj->metadata, metadata_size, GFP_KERNEL); if (!new_metadata) {
ret = -ENOMEM; goto out;
}
ret = msm_gem_lock_interruptible(obj); if (ret) return ret;
/* Avoid copy_to_user() under gem obj lock: */
len = msm_obj->metadata_size;
buf = kmemdup(msm_obj->metadata, len, GFP_KERNEL);
msm_gem_unlock(obj);
if (*metadata_size < len) {
ret = -ETOOSMALL;
} elseif (copy_to_user(metadata, buf, len)) {
ret = -EFAULT;
} else {
*metadata_size = len;
}
kfree(buf);
return0;
}
staticint msm_ioctl_gem_info(struct drm_device *dev, void *data, struct drm_file *file)
{ struct drm_msm_gem_info *args = data; struct drm_gem_object *obj; struct msm_gem_object *msm_obj; int i, ret = 0;
if (args->pad) return -EINVAL;
switch (args->info) { case MSM_INFO_GET_OFFSET: case MSM_INFO_GET_IOVA: case MSM_INFO_SET_IOVA: case MSM_INFO_GET_FLAGS: /* value returned as immediate, not pointer, so len==0: */ if (args->len) return -EINVAL; break; case MSM_INFO_SET_NAME: case MSM_INFO_GET_NAME: case MSM_INFO_SET_METADATA: case MSM_INFO_GET_METADATA: break; default: return -EINVAL;
}
obj = drm_gem_object_lookup(file, args->handle); if (!obj) return -ENOENT;
msm_obj = to_msm_bo(obj);
switch (args->info) { case MSM_INFO_GET_OFFSET:
args->value = msm_gem_mmap_offset(obj); break; case MSM_INFO_GET_IOVA:
ret = msm_ioctl_gem_info_iova(dev, file, obj, &args->value); break; case MSM_INFO_SET_IOVA:
ret = msm_ioctl_gem_info_set_iova(dev, file, obj, args->value); break; case MSM_INFO_GET_FLAGS: if (drm_gem_is_imported(obj)) {
ret = -EINVAL; break;
} /* Hide internal kernel-only flags: */
args->value = to_msm_bo(obj)->flags & MSM_BO_FLAGS;
ret = 0; break; case MSM_INFO_SET_NAME: /* length check should leave room for terminating null: */ if (args->len >= sizeof(msm_obj->name)) {
ret = -EINVAL; break;
} if (copy_from_user(msm_obj->name, u64_to_user_ptr(args->value),
args->len)) {
msm_obj->name[0] = '\0';
ret = -EFAULT; break;
}
msm_obj->name[args->len] = '\0'; for (i = 0; i < args->len; i++) { if (!isprint(msm_obj->name[i])) {
msm_obj->name[i] = '\0'; break;
}
} break; case MSM_INFO_GET_NAME: if (args->value && (args->len < strlen(msm_obj->name))) {
ret = -ETOOSMALL; break;
}
args->len = strlen(msm_obj->name); if (args->value) { if (copy_to_user(u64_to_user_ptr(args->value),
msm_obj->name, args->len))
ret = -EFAULT;
} break; case MSM_INFO_SET_METADATA:
ret = msm_ioctl_gem_info_set_metadata(
obj, u64_to_user_ptr(args->value), args->len); break; case MSM_INFO_GET_METADATA:
ret = msm_ioctl_gem_info_get_metadata(
obj, u64_to_user_ptr(args->value), &args->len); break;
}
ret = of_graph_parse_endpoint(ep_node, &ep); if (ret) {
DRM_DEV_ERROR(master_dev, "unable to parse port endpoint\n");
of_node_put(ep_node); return ret;
}
if (of_device_is_available(intf))
drm_of_component_match_add(master_dev, matchptr,
component_compare_of, intf);
of_node_put(intf);
}
return0;
}
#if !IS_REACHABLE(CONFIG_DRM_MSM_MDP5) || !IS_REACHABLE(CONFIG_DRM_MSM_DPU) bool msm_disp_drv_should_bind(struct device *dev, bool dpu_driver)
{ /* If just a single driver is enabled, use it no matter what */ returntrue;
} #else
staticbool prefer_mdp5 = true;
MODULE_PARM_DESC(prefer_mdp5, "Select whether MDP5 or DPU driver should be preferred");
module_param(prefer_mdp5, bool, 0444);
/* list all platforms supported by both mdp5 and dpu drivers */ staticconstchar *const msm_mdp5_dpu_migration[] = { "qcom,msm8917-mdp5", "qcom,msm8937-mdp5", "qcom,msm8953-mdp5", "qcom,msm8996-mdp5", "qcom,sdm630-mdp5", "qcom,sdm660-mdp5",
NULL,
};
bool msm_disp_drv_should_bind(struct device *dev, bool dpu_driver)
{ /* If it is not an MDP5 device, do not try MDP5 driver */ if (!of_device_is_compatible(dev->of_node, "qcom,mdp5")) return dpu_driver;
/* If it is not in the migration list, use MDP5 */ if (!of_device_compatible_match(dev->of_node, msm_mdp5_dpu_migration)) return !dpu_driver;
/* Add mdp components if we have KMS. */ if (kms_init) {
ret = add_mdp_components(master_dev, &match); if (ret) return ret;
}
if (!msm_gpu_no_components()) {
ret = add_gpu_components(master_dev, &match); if (ret) return ret;
}
/* on all devices that I am aware of, iommu's which can map *anyaddressthecpucanseeareused:
*/
ret = dma_set_mask_and_coherent(master_dev, ~0); if (ret) return ret;
ret = component_master_add_with_match(master_dev, &msm_drm_ops, match); if (ret) return ret;
return0;
}
int msm_gpu_probe(struct platform_device *pdev, conststruct component_ops *ops)
{ struct msm_drm_private *priv; int ret;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM;
platform_set_drvdata(pdev, priv);
/* on all devices that I am aware of, iommu's which can map *anyaddressthecpucanseeareused:
*/
ret = dma_set_mask_and_coherent(&pdev->dev, ~0); if (ret) return ret;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.