xref: /linux/drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
13b60b70dSJames Zhu /*
23b60b70dSJames Zhu  * Copyright 2023 Advanced Micro Devices, Inc.
33b60b70dSJames Zhu  *
43b60b70dSJames Zhu  * Permission is hereby granted, free of charge, to any person obtaining a
53b60b70dSJames Zhu  * copy of this software and associated documentation files (the "Software"),
63b60b70dSJames Zhu  * to deal in the Software without restriction, including without limitation
73b60b70dSJames Zhu  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
83b60b70dSJames Zhu  * and/or sell copies of the Software, and to permit persons to whom the
93b60b70dSJames Zhu  * Software is furnished to do so, subject to the following conditions:
103b60b70dSJames Zhu  *
113b60b70dSJames Zhu  * The above copyright notice and this permission notice shall be included in
123b60b70dSJames Zhu  * all copies or substantial portions of the Software.
133b60b70dSJames Zhu  *
143b60b70dSJames Zhu  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
153b60b70dSJames Zhu  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
163b60b70dSJames Zhu  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
173b60b70dSJames Zhu  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
183b60b70dSJames Zhu  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
193b60b70dSJames Zhu  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
203b60b70dSJames Zhu  * OTHER DEALINGS IN THE SOFTWARE.
213b60b70dSJames Zhu  *
223b60b70dSJames Zhu  */
233b60b70dSJames Zhu 
243b60b70dSJames Zhu #include <linux/init.h>
253b60b70dSJames Zhu #include <linux/module.h>
263b60b70dSJames Zhu #include <linux/platform_device.h>
273b60b70dSJames Zhu 
283b60b70dSJames Zhu #include <drm/drm_drv.h>
293b60b70dSJames Zhu 
303b60b70dSJames Zhu #include "amdgpu_xcp_drv.h"
313b60b70dSJames Zhu 
323b60b70dSJames Zhu #define MAX_XCP_PLATFORM_DEVICE 64
333b60b70dSJames Zhu 
343b60b70dSJames Zhu struct xcp_device {
353b60b70dSJames Zhu 	struct drm_device drm;
363b60b70dSJames Zhu 	struct platform_device *pdev;
373b60b70dSJames Zhu };
383b60b70dSJames Zhu 
393b60b70dSJames Zhu static const struct drm_driver amdgpu_xcp_driver = {
403b60b70dSJames Zhu 	.driver_features = DRIVER_GEM | DRIVER_RENDER,
413b60b70dSJames Zhu 	.name = "amdgpu_xcp_drv",
423b60b70dSJames Zhu 	.major = 1,
433b60b70dSJames Zhu 	.minor = 0,
443b60b70dSJames Zhu };
453b60b70dSJames Zhu 
46*a641c25fSLijo Lazar static int8_t pdev_num;
473b60b70dSJames Zhu static struct xcp_device *xcp_dev[MAX_XCP_PLATFORM_DEVICE];
483b60b70dSJames Zhu 
amdgpu_xcp_drm_dev_alloc(struct drm_device ** ddev)493b60b70dSJames Zhu int amdgpu_xcp_drm_dev_alloc(struct drm_device **ddev)
503b60b70dSJames Zhu {
513b60b70dSJames Zhu 	struct platform_device *pdev;
523b60b70dSJames Zhu 	struct xcp_device *pxcp_dev;
5397d814feSLijo Lazar 	char dev_name[20];
543b60b70dSJames Zhu 	int ret;
553b60b70dSJames Zhu 
563b60b70dSJames Zhu 	if (pdev_num >= MAX_XCP_PLATFORM_DEVICE)
573b60b70dSJames Zhu 		return -ENODEV;
583b60b70dSJames Zhu 
5997d814feSLijo Lazar 	snprintf(dev_name, sizeof(dev_name), "amdgpu_xcp_%d", pdev_num);
6097d814feSLijo Lazar 	pdev = platform_device_register_simple(dev_name, -1, NULL, 0);
613b60b70dSJames Zhu 	if (IS_ERR(pdev))
623b60b70dSJames Zhu 		return PTR_ERR(pdev);
633b60b70dSJames Zhu 
643b60b70dSJames Zhu 	if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) {
653b60b70dSJames Zhu 		ret = -ENOMEM;
663b60b70dSJames Zhu 		goto out_unregister;
673b60b70dSJames Zhu 	}
683b60b70dSJames Zhu 
693b60b70dSJames Zhu 	pxcp_dev = devm_drm_dev_alloc(&pdev->dev, &amdgpu_xcp_driver, struct xcp_device, drm);
703b60b70dSJames Zhu 	if (IS_ERR(pxcp_dev)) {
713b60b70dSJames Zhu 		ret = PTR_ERR(pxcp_dev);
723b60b70dSJames Zhu 		goto out_devres;
733b60b70dSJames Zhu 	}
743b60b70dSJames Zhu 
753b60b70dSJames Zhu 	xcp_dev[pdev_num] = pxcp_dev;
763b60b70dSJames Zhu 	xcp_dev[pdev_num]->pdev = pdev;
773b60b70dSJames Zhu 	*ddev = &pxcp_dev->drm;
783b60b70dSJames Zhu 	pdev_num++;
793b60b70dSJames Zhu 
803b60b70dSJames Zhu 	return 0;
813b60b70dSJames Zhu 
823b60b70dSJames Zhu out_devres:
833b60b70dSJames Zhu 	devres_release_group(&pdev->dev, NULL);
843b60b70dSJames Zhu out_unregister:
853b60b70dSJames Zhu 	platform_device_unregister(pdev);
863b60b70dSJames Zhu 
873b60b70dSJames Zhu 	return ret;
883b60b70dSJames Zhu }
893b60b70dSJames Zhu EXPORT_SYMBOL(amdgpu_xcp_drm_dev_alloc);
903b60b70dSJames Zhu 
amdgpu_xcp_drv_release(void)913b60b70dSJames Zhu void amdgpu_xcp_drv_release(void)
923b60b70dSJames Zhu {
933b60b70dSJames Zhu 	for (--pdev_num; pdev_num >= 0; --pdev_num) {
94e2ae32d8SJames Zhu 		struct platform_device *pdev = xcp_dev[pdev_num]->pdev;
95e2ae32d8SJames Zhu 
96e2ae32d8SJames Zhu 		devres_release_group(&pdev->dev, NULL);
97e2ae32d8SJames Zhu 		platform_device_unregister(pdev);
983b60b70dSJames Zhu 		xcp_dev[pdev_num] = NULL;
993b60b70dSJames Zhu 	}
1003b60b70dSJames Zhu 	pdev_num = 0;
1013b60b70dSJames Zhu }
1023b60b70dSJames Zhu EXPORT_SYMBOL(amdgpu_xcp_drv_release);
1033b60b70dSJames Zhu 
amdgpu_xcp_drv_exit(void)1043b60b70dSJames Zhu static void __exit amdgpu_xcp_drv_exit(void)
1053b60b70dSJames Zhu {
1063b60b70dSJames Zhu 	amdgpu_xcp_drv_release();
1073b60b70dSJames Zhu }
1083b60b70dSJames Zhu 
1093b60b70dSJames Zhu module_exit(amdgpu_xcp_drv_exit);
1103b60b70dSJames Zhu 
1113b60b70dSJames Zhu MODULE_AUTHOR("AMD linux driver team");
1123b60b70dSJames Zhu MODULE_DESCRIPTION("AMD XCP PLATFORM DEVICES");
1133b60b70dSJames Zhu MODULE_LICENSE("GPL and additional rights");
114