126bd43a7Sjames qian wang (Arm Technology China) // SPDX-License-Identifier: GPL-2.0
226bd43a7Sjames qian wang (Arm Technology China) /*
326bd43a7Sjames qian wang (Arm Technology China) * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
426bd43a7Sjames qian wang (Arm Technology China) * Author: James.Qian.Wang <james.qian.wang@arm.com>
526bd43a7Sjames qian wang (Arm Technology China) *
626bd43a7Sjames qian wang (Arm Technology China) */
726bd43a7Sjames qian wang (Arm Technology China) #include <linux/module.h>
826bd43a7Sjames qian wang (Arm Technology China) #include <linux/kernel.h>
9fb28b3f0SThomas Zimmermann #include <linux/of.h>
1026bd43a7Sjames qian wang (Arm Technology China) #include <linux/platform_device.h>
112ebb6701SLowry Li (Arm Technology China) #include <linux/pm_runtime.h>
12386030e5SThomas Zimmermann #include <drm/drm_fbdev_dma.h>
13e0f8cd23SJavier Martinez Canillas #include <drm/drm_module.h>
1426bd43a7Sjames qian wang (Arm Technology China) #include <drm/drm_of.h>
1526bd43a7Sjames qian wang (Arm Technology China) #include "komeda_dev.h"
1661f1c4a8Sjames qian wang (Arm Technology China) #include "komeda_kms.h"
1726bd43a7Sjames qian wang (Arm Technology China)
1826bd43a7Sjames qian wang (Arm Technology China) struct komeda_drv {
1926bd43a7Sjames qian wang (Arm Technology China) struct komeda_dev *mdev;
2061f1c4a8Sjames qian wang (Arm Technology China) struct komeda_kms_dev *kms;
2126bd43a7Sjames qian wang (Arm Technology China) };
2226bd43a7Sjames qian wang (Arm Technology China)
dev_to_mdev(struct device * dev)2355223394Sjames qian wang (Arm Technology China) struct komeda_dev *dev_to_mdev(struct device *dev)
2455223394Sjames qian wang (Arm Technology China) {
2555223394Sjames qian wang (Arm Technology China) struct komeda_drv *mdrv = dev_get_drvdata(dev);
2655223394Sjames qian wang (Arm Technology China)
2755223394Sjames qian wang (Arm Technology China) return mdrv ? mdrv->mdev : NULL;
2855223394Sjames qian wang (Arm Technology China) }
2955223394Sjames qian wang (Arm Technology China)
komeda_platform_remove(struct platform_device * pdev)304cfe5cc0SFaiz Abbas static void komeda_platform_remove(struct platform_device *pdev)
3126bd43a7Sjames qian wang (Arm Technology China) {
324cfe5cc0SFaiz Abbas struct device *dev = &pdev->dev;
3326bd43a7Sjames qian wang (Arm Technology China) struct komeda_drv *mdrv = dev_get_drvdata(dev);
3426bd43a7Sjames qian wang (Arm Technology China)
3561f1c4a8Sjames qian wang (Arm Technology China) komeda_kms_detach(mdrv->kms);
36efb46508Sjames qian wang (Arm Technology China)
37efb46508Sjames qian wang (Arm Technology China) if (pm_runtime_enabled(dev))
38efb46508Sjames qian wang (Arm Technology China) pm_runtime_disable(dev);
39efb46508Sjames qian wang (Arm Technology China) else
40efb46508Sjames qian wang (Arm Technology China) komeda_dev_suspend(mdrv->mdev);
41efb46508Sjames qian wang (Arm Technology China)
4226bd43a7Sjames qian wang (Arm Technology China) komeda_dev_destroy(mdrv->mdev);
4326bd43a7Sjames qian wang (Arm Technology China)
4426bd43a7Sjames qian wang (Arm Technology China) dev_set_drvdata(dev, NULL);
4526bd43a7Sjames qian wang (Arm Technology China) devm_kfree(dev, mdrv);
4626bd43a7Sjames qian wang (Arm Technology China) }
4726bd43a7Sjames qian wang (Arm Technology China)
komeda_platform_shutdown(struct platform_device * pdev)48ce3d99c8SDouglas Anderson static void komeda_platform_shutdown(struct platform_device *pdev)
49ce3d99c8SDouglas Anderson {
50ce3d99c8SDouglas Anderson struct device *dev = &pdev->dev;
51ce3d99c8SDouglas Anderson struct komeda_drv *mdrv = dev_get_drvdata(dev);
52ce3d99c8SDouglas Anderson
53ce3d99c8SDouglas Anderson komeda_kms_shutdown(mdrv->kms);
54ce3d99c8SDouglas Anderson }
55ce3d99c8SDouglas Anderson
komeda_platform_probe(struct platform_device * pdev)564cfe5cc0SFaiz Abbas static int komeda_platform_probe(struct platform_device *pdev)
5726bd43a7Sjames qian wang (Arm Technology China) {
584cfe5cc0SFaiz Abbas struct device *dev = &pdev->dev;
5926bd43a7Sjames qian wang (Arm Technology China) struct komeda_drv *mdrv;
6026bd43a7Sjames qian wang (Arm Technology China) int err;
6126bd43a7Sjames qian wang (Arm Technology China)
62*a918dcfeSAmjad Ouled-Ameur err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40));
63*a918dcfeSAmjad Ouled-Ameur if (err)
64*a918dcfeSAmjad Ouled-Ameur return dev_err_probe(dev, err, "DMA mask error\n");
65*a918dcfeSAmjad Ouled-Ameur
6626bd43a7Sjames qian wang (Arm Technology China) mdrv = devm_kzalloc(dev, sizeof(*mdrv), GFP_KERNEL);
6726bd43a7Sjames qian wang (Arm Technology China) if (!mdrv)
6826bd43a7Sjames qian wang (Arm Technology China) return -ENOMEM;
6926bd43a7Sjames qian wang (Arm Technology China)
7026bd43a7Sjames qian wang (Arm Technology China) mdrv->mdev = komeda_dev_create(dev);
7126bd43a7Sjames qian wang (Arm Technology China) if (IS_ERR(mdrv->mdev)) {
7226bd43a7Sjames qian wang (Arm Technology China) err = PTR_ERR(mdrv->mdev);
7326bd43a7Sjames qian wang (Arm Technology China) goto free_mdrv;
7426bd43a7Sjames qian wang (Arm Technology China) }
7526bd43a7Sjames qian wang (Arm Technology China)
76efb46508Sjames qian wang (Arm Technology China) pm_runtime_enable(dev);
77efb46508Sjames qian wang (Arm Technology China) if (!pm_runtime_enabled(dev))
78efb46508Sjames qian wang (Arm Technology China) komeda_dev_resume(mdrv->mdev);
79efb46508Sjames qian wang (Arm Technology China)
8061f1c4a8Sjames qian wang (Arm Technology China) mdrv->kms = komeda_kms_attach(mdrv->mdev);
8161f1c4a8Sjames qian wang (Arm Technology China) if (IS_ERR(mdrv->kms)) {
8261f1c4a8Sjames qian wang (Arm Technology China) err = PTR_ERR(mdrv->kms);
8361f1c4a8Sjames qian wang (Arm Technology China) goto destroy_mdev;
8461f1c4a8Sjames qian wang (Arm Technology China) }
8561f1c4a8Sjames qian wang (Arm Technology China)
8626bd43a7Sjames qian wang (Arm Technology China) dev_set_drvdata(dev, mdrv);
87386030e5SThomas Zimmermann drm_fbdev_dma_setup(&mdrv->kms->base, 32);
8826bd43a7Sjames qian wang (Arm Technology China)
8926bd43a7Sjames qian wang (Arm Technology China) return 0;
9026bd43a7Sjames qian wang (Arm Technology China)
9161f1c4a8Sjames qian wang (Arm Technology China) destroy_mdev:
92efb46508Sjames qian wang (Arm Technology China) if (pm_runtime_enabled(dev))
93efb46508Sjames qian wang (Arm Technology China) pm_runtime_disable(dev);
94efb46508Sjames qian wang (Arm Technology China) else
95efb46508Sjames qian wang (Arm Technology China) komeda_dev_suspend(mdrv->mdev);
96efb46508Sjames qian wang (Arm Technology China)
9761f1c4a8Sjames qian wang (Arm Technology China) komeda_dev_destroy(mdrv->mdev);
9861f1c4a8Sjames qian wang (Arm Technology China)
9926bd43a7Sjames qian wang (Arm Technology China) free_mdrv:
10026bd43a7Sjames qian wang (Arm Technology China) devm_kfree(dev, mdrv);
10126bd43a7Sjames qian wang (Arm Technology China) return err;
10226bd43a7Sjames qian wang (Arm Technology China) }
10326bd43a7Sjames qian wang (Arm Technology China)
10415e9122dSjames qian wang (Arm Technology China) static const struct of_device_id komeda_of_match[] = {
105b25bc78fSjames qian wang (Arm Technology China) { .compatible = "arm,mali-d71", .data = d71_identify, },
10617cfcb68Sjames qian wang (Arm Technology China) { .compatible = "arm,mali-d32", .data = d71_identify, },
10726bd43a7Sjames qian wang (Arm Technology China) {},
10826bd43a7Sjames qian wang (Arm Technology China) };
10926bd43a7Sjames qian wang (Arm Technology China)
11026bd43a7Sjames qian wang (Arm Technology China) MODULE_DEVICE_TABLE(of, komeda_of_match);
11126bd43a7Sjames qian wang (Arm Technology China)
komeda_rt_pm_suspend(struct device * dev)1129803aac7SArnd Bergmann static int __maybe_unused komeda_rt_pm_suspend(struct device *dev)
113efb46508Sjames qian wang (Arm Technology China) {
114efb46508Sjames qian wang (Arm Technology China) struct komeda_drv *mdrv = dev_get_drvdata(dev);
115efb46508Sjames qian wang (Arm Technology China)
116efb46508Sjames qian wang (Arm Technology China) return komeda_dev_suspend(mdrv->mdev);
117efb46508Sjames qian wang (Arm Technology China) }
118efb46508Sjames qian wang (Arm Technology China)
komeda_rt_pm_resume(struct device * dev)1199803aac7SArnd Bergmann static int __maybe_unused komeda_rt_pm_resume(struct device *dev)
120efb46508Sjames qian wang (Arm Technology China) {
121efb46508Sjames qian wang (Arm Technology China) struct komeda_drv *mdrv = dev_get_drvdata(dev);
122efb46508Sjames qian wang (Arm Technology China)
123efb46508Sjames qian wang (Arm Technology China) return komeda_dev_resume(mdrv->mdev);
124efb46508Sjames qian wang (Arm Technology China) }
125efb46508Sjames qian wang (Arm Technology China)
komeda_pm_suspend(struct device * dev)1262ebb6701SLowry Li (Arm Technology China) static int __maybe_unused komeda_pm_suspend(struct device *dev)
1272ebb6701SLowry Li (Arm Technology China) {
1282ebb6701SLowry Li (Arm Technology China) struct komeda_drv *mdrv = dev_get_drvdata(dev);
1292ebb6701SLowry Li (Arm Technology China) int res;
1302ebb6701SLowry Li (Arm Technology China)
131efb46508Sjames qian wang (Arm Technology China) res = drm_mode_config_helper_suspend(&mdrv->kms->base);
1322ebb6701SLowry Li (Arm Technology China)
133efb46508Sjames qian wang (Arm Technology China) if (!pm_runtime_status_suspended(dev))
1342ebb6701SLowry Li (Arm Technology China) komeda_dev_suspend(mdrv->mdev);
1352ebb6701SLowry Li (Arm Technology China)
1362ebb6701SLowry Li (Arm Technology China) return res;
1372ebb6701SLowry Li (Arm Technology China) }
1382ebb6701SLowry Li (Arm Technology China)
komeda_pm_resume(struct device * dev)1392ebb6701SLowry Li (Arm Technology China) static int __maybe_unused komeda_pm_resume(struct device *dev)
1402ebb6701SLowry Li (Arm Technology China) {
1412ebb6701SLowry Li (Arm Technology China) struct komeda_drv *mdrv = dev_get_drvdata(dev);
1422ebb6701SLowry Li (Arm Technology China)
143efb46508Sjames qian wang (Arm Technology China) if (!pm_runtime_status_suspended(dev))
1442ebb6701SLowry Li (Arm Technology China) komeda_dev_resume(mdrv->mdev);
1452ebb6701SLowry Li (Arm Technology China)
146efb46508Sjames qian wang (Arm Technology China) return drm_mode_config_helper_resume(&mdrv->kms->base);
1472ebb6701SLowry Li (Arm Technology China) }
1482ebb6701SLowry Li (Arm Technology China)
1492ebb6701SLowry Li (Arm Technology China) static const struct dev_pm_ops komeda_pm_ops = {
1502ebb6701SLowry Li (Arm Technology China) SET_SYSTEM_SLEEP_PM_OPS(komeda_pm_suspend, komeda_pm_resume)
151efb46508Sjames qian wang (Arm Technology China) SET_RUNTIME_PM_OPS(komeda_rt_pm_suspend, komeda_rt_pm_resume, NULL)
1522ebb6701SLowry Li (Arm Technology China) };
1532ebb6701SLowry Li (Arm Technology China)
15426bd43a7Sjames qian wang (Arm Technology China) static struct platform_driver komeda_platform_driver = {
15526bd43a7Sjames qian wang (Arm Technology China) .probe = komeda_platform_probe,
1561bf3d76aSUwe Kleine-König .remove_new = komeda_platform_remove,
157ce3d99c8SDouglas Anderson .shutdown = komeda_platform_shutdown,
15826bd43a7Sjames qian wang (Arm Technology China) .driver = {
15926bd43a7Sjames qian wang (Arm Technology China) .name = "komeda",
16026bd43a7Sjames qian wang (Arm Technology China) .of_match_table = komeda_of_match,
1612ebb6701SLowry Li (Arm Technology China) .pm = &komeda_pm_ops,
16226bd43a7Sjames qian wang (Arm Technology China) },
16326bd43a7Sjames qian wang (Arm Technology China) };
16426bd43a7Sjames qian wang (Arm Technology China)
165e0f8cd23SJavier Martinez Canillas drm_module_platform_driver(komeda_platform_driver);
16626bd43a7Sjames qian wang (Arm Technology China)
16726bd43a7Sjames qian wang (Arm Technology China) MODULE_AUTHOR("James.Qian.Wang <james.qian.wang@arm.com>");
16826bd43a7Sjames qian wang (Arm Technology China) MODULE_DESCRIPTION("Komeda KMS driver");
16926bd43a7Sjames qian wang (Arm Technology China) MODULE_LICENSE("GPL v2");
170