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