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>
128ab59da2SThomas Zimmermann #include <drm/drm_fbdev_generic.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)30*4cfe5cc0SFaiz Abbas static void komeda_platform_remove(struct platform_device *pdev)
3126bd43a7Sjames qian wang (Arm Technology China) {
32*4cfe5cc0SFaiz 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_probe(struct platform_device * pdev)48*4cfe5cc0SFaiz Abbas static int komeda_platform_probe(struct platform_device *pdev)
4926bd43a7Sjames qian wang (Arm Technology China) {
50*4cfe5cc0SFaiz Abbas 	struct device *dev = &pdev->dev;
5126bd43a7Sjames qian wang (Arm Technology China) 	struct komeda_drv *mdrv;
5226bd43a7Sjames qian wang (Arm Technology China) 	int err;
5326bd43a7Sjames qian wang (Arm Technology China) 
5426bd43a7Sjames qian wang (Arm Technology China) 	mdrv = devm_kzalloc(dev, sizeof(*mdrv), GFP_KERNEL);
5526bd43a7Sjames qian wang (Arm Technology China) 	if (!mdrv)
5626bd43a7Sjames qian wang (Arm Technology China) 		return -ENOMEM;
5726bd43a7Sjames qian wang (Arm Technology China) 
5826bd43a7Sjames qian wang (Arm Technology China) 	mdrv->mdev = komeda_dev_create(dev);
5926bd43a7Sjames qian wang (Arm Technology China) 	if (IS_ERR(mdrv->mdev)) {
6026bd43a7Sjames qian wang (Arm Technology China) 		err = PTR_ERR(mdrv->mdev);
6126bd43a7Sjames qian wang (Arm Technology China) 		goto free_mdrv;
6226bd43a7Sjames qian wang (Arm Technology China) 	}
6326bd43a7Sjames qian wang (Arm Technology China) 
64efb46508Sjames qian wang (Arm Technology China) 	pm_runtime_enable(dev);
65efb46508Sjames qian wang (Arm Technology China) 	if (!pm_runtime_enabled(dev))
66efb46508Sjames qian wang (Arm Technology China) 		komeda_dev_resume(mdrv->mdev);
67efb46508Sjames qian wang (Arm Technology China) 
6861f1c4a8Sjames qian wang (Arm Technology China) 	mdrv->kms = komeda_kms_attach(mdrv->mdev);
6961f1c4a8Sjames qian wang (Arm Technology China) 	if (IS_ERR(mdrv->kms)) {
7061f1c4a8Sjames qian wang (Arm Technology China) 		err = PTR_ERR(mdrv->kms);
7161f1c4a8Sjames qian wang (Arm Technology China) 		goto destroy_mdev;
7261f1c4a8Sjames qian wang (Arm Technology China) 	}
7361f1c4a8Sjames qian wang (Arm Technology China) 
7426bd43a7Sjames qian wang (Arm Technology China) 	dev_set_drvdata(dev, mdrv);
75000a2f04SCarsten Haitzler 	drm_fbdev_generic_setup(&mdrv->kms->base, 32);
7626bd43a7Sjames qian wang (Arm Technology China) 
7726bd43a7Sjames qian wang (Arm Technology China) 	return 0;
7826bd43a7Sjames qian wang (Arm Technology China) 
7961f1c4a8Sjames qian wang (Arm Technology China) destroy_mdev:
80efb46508Sjames qian wang (Arm Technology China) 	if (pm_runtime_enabled(dev))
81efb46508Sjames qian wang (Arm Technology China) 		pm_runtime_disable(dev);
82efb46508Sjames qian wang (Arm Technology China) 	else
83efb46508Sjames qian wang (Arm Technology China) 		komeda_dev_suspend(mdrv->mdev);
84efb46508Sjames qian wang (Arm Technology China) 
8561f1c4a8Sjames qian wang (Arm Technology China) 	komeda_dev_destroy(mdrv->mdev);
8661f1c4a8Sjames qian wang (Arm Technology China) 
8726bd43a7Sjames qian wang (Arm Technology China) free_mdrv:
8826bd43a7Sjames qian wang (Arm Technology China) 	devm_kfree(dev, mdrv);
8926bd43a7Sjames qian wang (Arm Technology China) 	return err;
9026bd43a7Sjames qian wang (Arm Technology China) }
9126bd43a7Sjames qian wang (Arm Technology China) 
9215e9122dSjames qian wang (Arm Technology China) static const struct of_device_id komeda_of_match[] = {
93b25bc78fSjames qian wang (Arm Technology China) 	{ .compatible = "arm,mali-d71", .data = d71_identify, },
9417cfcb68Sjames qian wang (Arm Technology China) 	{ .compatible = "arm,mali-d32", .data = d71_identify, },
9526bd43a7Sjames qian wang (Arm Technology China) 	{},
9626bd43a7Sjames qian wang (Arm Technology China) };
9726bd43a7Sjames qian wang (Arm Technology China) 
9826bd43a7Sjames qian wang (Arm Technology China) MODULE_DEVICE_TABLE(of, komeda_of_match);
9926bd43a7Sjames qian wang (Arm Technology China) 
komeda_rt_pm_suspend(struct device * dev)1009803aac7SArnd Bergmann static int __maybe_unused komeda_rt_pm_suspend(struct device *dev)
101efb46508Sjames qian wang (Arm Technology China) {
102efb46508Sjames qian wang (Arm Technology China) 	struct komeda_drv *mdrv = dev_get_drvdata(dev);
103efb46508Sjames qian wang (Arm Technology China) 
104efb46508Sjames qian wang (Arm Technology China) 	return komeda_dev_suspend(mdrv->mdev);
105efb46508Sjames qian wang (Arm Technology China) }
106efb46508Sjames qian wang (Arm Technology China) 
komeda_rt_pm_resume(struct device * dev)1079803aac7SArnd Bergmann static int __maybe_unused komeda_rt_pm_resume(struct device *dev)
108efb46508Sjames qian wang (Arm Technology China) {
109efb46508Sjames qian wang (Arm Technology China) 	struct komeda_drv *mdrv = dev_get_drvdata(dev);
110efb46508Sjames qian wang (Arm Technology China) 
111efb46508Sjames qian wang (Arm Technology China) 	return komeda_dev_resume(mdrv->mdev);
112efb46508Sjames qian wang (Arm Technology China) }
113efb46508Sjames qian wang (Arm Technology China) 
komeda_pm_suspend(struct device * dev)1142ebb6701SLowry Li (Arm Technology China) static int __maybe_unused komeda_pm_suspend(struct device *dev)
1152ebb6701SLowry Li (Arm Technology China) {
1162ebb6701SLowry Li (Arm Technology China) 	struct komeda_drv *mdrv = dev_get_drvdata(dev);
1172ebb6701SLowry Li (Arm Technology China) 	int res;
1182ebb6701SLowry Li (Arm Technology China) 
119efb46508Sjames qian wang (Arm Technology China) 	res = drm_mode_config_helper_suspend(&mdrv->kms->base);
1202ebb6701SLowry Li (Arm Technology China) 
121efb46508Sjames qian wang (Arm Technology China) 	if (!pm_runtime_status_suspended(dev))
1222ebb6701SLowry Li (Arm Technology China) 		komeda_dev_suspend(mdrv->mdev);
1232ebb6701SLowry Li (Arm Technology China) 
1242ebb6701SLowry Li (Arm Technology China) 	return res;
1252ebb6701SLowry Li (Arm Technology China) }
1262ebb6701SLowry Li (Arm Technology China) 
komeda_pm_resume(struct device * dev)1272ebb6701SLowry Li (Arm Technology China) static int __maybe_unused komeda_pm_resume(struct device *dev)
1282ebb6701SLowry Li (Arm Technology China) {
1292ebb6701SLowry Li (Arm Technology China) 	struct komeda_drv *mdrv = dev_get_drvdata(dev);
1302ebb6701SLowry Li (Arm Technology China) 
131efb46508Sjames qian wang (Arm Technology China) 	if (!pm_runtime_status_suspended(dev))
1322ebb6701SLowry Li (Arm Technology China) 		komeda_dev_resume(mdrv->mdev);
1332ebb6701SLowry Li (Arm Technology China) 
134efb46508Sjames qian wang (Arm Technology China) 	return drm_mode_config_helper_resume(&mdrv->kms->base);
1352ebb6701SLowry Li (Arm Technology China) }
1362ebb6701SLowry Li (Arm Technology China) 
1372ebb6701SLowry Li (Arm Technology China) static const struct dev_pm_ops komeda_pm_ops = {
1382ebb6701SLowry Li (Arm Technology China) 	SET_SYSTEM_SLEEP_PM_OPS(komeda_pm_suspend, komeda_pm_resume)
139efb46508Sjames qian wang (Arm Technology China) 	SET_RUNTIME_PM_OPS(komeda_rt_pm_suspend, komeda_rt_pm_resume, NULL)
1402ebb6701SLowry Li (Arm Technology China) };
1412ebb6701SLowry Li (Arm Technology China) 
14226bd43a7Sjames qian wang (Arm Technology China) static struct platform_driver komeda_platform_driver = {
14326bd43a7Sjames qian wang (Arm Technology China) 	.probe	= komeda_platform_probe,
1441bf3d76aSUwe Kleine-König 	.remove_new = komeda_platform_remove,
14526bd43a7Sjames qian wang (Arm Technology China) 	.driver	= {
14626bd43a7Sjames qian wang (Arm Technology China) 		.name = "komeda",
14726bd43a7Sjames qian wang (Arm Technology China) 		.of_match_table	= komeda_of_match,
1482ebb6701SLowry Li (Arm Technology China) 		.pm = &komeda_pm_ops,
14926bd43a7Sjames qian wang (Arm Technology China) 	},
15026bd43a7Sjames qian wang (Arm Technology China) };
15126bd43a7Sjames qian wang (Arm Technology China) 
152e0f8cd23SJavier Martinez Canillas drm_module_platform_driver(komeda_platform_driver);
15326bd43a7Sjames qian wang (Arm Technology China) 
15426bd43a7Sjames qian wang (Arm Technology China) MODULE_AUTHOR("James.Qian.Wang <james.qian.wang@arm.com>");
15526bd43a7Sjames qian wang (Arm Technology China) MODULE_DESCRIPTION("Komeda KMS driver");
15626bd43a7Sjames qian wang (Arm Technology China) MODULE_LICENSE("GPL v2");
157