1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2020 Unisoc Inc.
6 #include <linux/component.h>
7 #include <linux/dma-mapping.h>
8 #include <linux/mod_devicetable.h>
9 #include <linux/module.h>
10 #include <linux/mutex.h>
11 #include <linux/of_graph.h>
12 #include <linux/platform_device.h>
14 #include <drm/drm_atomic_helper.h>
15 #include <drm/drm_drv.h>
16 #include <drm/drm_gem_dma_helper.h>
17 #include <drm/drm_gem_framebuffer_helper.h>
18 #include <drm/drm_of.h>
19 #include <drm/drm_probe_helper.h>
20 #include <drm/drm_vblank.h>
24 #define DRIVER_NAME "sprd"
25 #define DRIVER_DESC "Spreadtrum SoCs' DRM Driver"
26 #define DRIVER_DATE "20200201"
27 #define DRIVER_MAJOR 1
28 #define DRIVER_MINOR 0
30 static const struct drm_mode_config_helper_funcs sprd_drm_mode_config_helper
= {
31 .atomic_commit_tail
= drm_atomic_helper_commit_tail_rpm
,
34 static const struct drm_mode_config_funcs sprd_drm_mode_config_funcs
= {
35 .fb_create
= drm_gem_fb_create
,
36 .atomic_check
= drm_atomic_helper_check
,
37 .atomic_commit
= drm_atomic_helper_commit
,
40 static void sprd_drm_mode_config_init(struct drm_device
*drm
)
42 drm
->mode_config
.min_width
= 0;
43 drm
->mode_config
.min_height
= 0;
44 drm
->mode_config
.max_width
= 8192;
45 drm
->mode_config
.max_height
= 8192;
47 drm
->mode_config
.funcs
= &sprd_drm_mode_config_funcs
;
48 drm
->mode_config
.helper_private
= &sprd_drm_mode_config_helper
;
51 DEFINE_DRM_GEM_DMA_FOPS(sprd_drm_fops
);
53 static struct drm_driver sprd_drm_drv
= {
54 .driver_features
= DRIVER_GEM
| DRIVER_MODESET
| DRIVER_ATOMIC
,
55 .fops
= &sprd_drm_fops
,
58 DRM_GEM_DMA_DRIVER_OPS
,
63 .major
= DRIVER_MAJOR
,
64 .minor
= DRIVER_MINOR
,
67 static int sprd_drm_bind(struct device
*dev
)
69 struct platform_device
*pdev
= to_platform_device(dev
);
70 struct drm_device
*drm
;
71 struct sprd_drm
*sprd
;
74 sprd
= devm_drm_dev_alloc(dev
, &sprd_drm_drv
, struct sprd_drm
, drm
);
79 platform_set_drvdata(pdev
, drm
);
81 ret
= drmm_mode_config_init(drm
);
85 sprd_drm_mode_config_init(drm
);
87 /* bind and init sub drivers */
88 ret
= component_bind_all(drm
->dev
, drm
);
90 drm_err(drm
, "failed to bind all component.\n");
95 ret
= drm_vblank_init(drm
, drm
->mode_config
.num_crtc
);
97 drm_err(drm
, "failed to initialize vblank.\n");
101 /* reset all the states of crtc/plane/encoder/connector */
102 drm_mode_config_reset(drm
);
104 /* init kms poll for handling hpd */
105 drm_kms_helper_poll_init(drm
);
107 ret
= drm_dev_register(drm
, 0);
109 goto err_kms_helper_poll_fini
;
113 err_kms_helper_poll_fini
:
114 drm_kms_helper_poll_fini(drm
);
116 component_unbind_all(drm
->dev
, drm
);
120 static void sprd_drm_unbind(struct device
*dev
)
122 struct drm_device
*drm
= dev_get_drvdata(dev
);
124 drm_dev_unregister(drm
);
126 drm_kms_helper_poll_fini(drm
);
128 component_unbind_all(drm
->dev
, drm
);
131 static const struct component_master_ops drm_component_ops
= {
132 .bind
= sprd_drm_bind
,
133 .unbind
= sprd_drm_unbind
,
136 static int sprd_drm_probe(struct platform_device
*pdev
)
138 return drm_of_component_probe(&pdev
->dev
, component_compare_of
, &drm_component_ops
);
141 static void sprd_drm_remove(struct platform_device
*pdev
)
143 component_master_del(&pdev
->dev
, &drm_component_ops
);
146 static void sprd_drm_shutdown(struct platform_device
*pdev
)
148 struct drm_device
*drm
= platform_get_drvdata(pdev
);
151 dev_warn(&pdev
->dev
, "drm device is not available, no shutdown\n");
155 drm_atomic_helper_shutdown(drm
);
158 static const struct of_device_id drm_match_table
[] = {
159 { .compatible
= "sprd,display-subsystem", },
162 MODULE_DEVICE_TABLE(of
, drm_match_table
);
164 static struct platform_driver sprd_drm_driver
= {
165 .probe
= sprd_drm_probe
,
166 .remove
= sprd_drm_remove
,
167 .shutdown
= sprd_drm_shutdown
,
169 .name
= "sprd-drm-drv",
170 .of_match_table
= drm_match_table
,
174 static struct platform_driver
*sprd_drm_drivers
[] = {
180 static int __init
sprd_drm_init(void)
182 if (drm_firmware_drivers_only())
185 return platform_register_drivers(sprd_drm_drivers
,
186 ARRAY_SIZE(sprd_drm_drivers
));
189 static void __exit
sprd_drm_exit(void)
191 platform_unregister_drivers(sprd_drm_drivers
,
192 ARRAY_SIZE(sprd_drm_drivers
));
195 module_init(sprd_drm_init
);
196 module_exit(sprd_drm_exit
);
198 MODULE_AUTHOR("Leon He <leon.he@unisoc.com>");
199 MODULE_AUTHOR("Kevin Tang <kevin.tang@unisoc.com>");
200 MODULE_DESCRIPTION("Unisoc DRM KMS Master Driver");
201 MODULE_LICENSE("GPL v2");