1 // SPDX-License-Identifier: GPL-2.0-only
3 * Hisilicon Kirin SoCs drm master driver
5 * Copyright (c) 2016 Linaro Limited.
6 * Copyright (c) 2014-2016 Hisilicon Limited.
9 * Xinliang Liu <z.liuxinliang@hisilicon.com>
10 * Xinliang Liu <xinliang.liu@linaro.org>
11 * Xinwei Kong <kong.kongxinwei@hisilicon.com>
14 #include <linux/of_platform.h>
15 #include <linux/component.h>
16 #include <linux/module.h>
17 #include <linux/of_graph.h>
18 #include <linux/platform_device.h>
20 #include <drm/drm_atomic_helper.h>
21 #include <drm/drm_drv.h>
22 #include <drm/drm_fb_cma_helper.h>
23 #include <drm/drm_fb_helper.h>
24 #include <drm/drm_gem_cma_helper.h>
25 #include <drm/drm_gem_framebuffer_helper.h>
26 #include <drm/drm_of.h>
27 #include <drm/drm_probe_helper.h>
28 #include <drm/drm_vblank.h>
30 #include "kirin_drm_drv.h"
32 static struct kirin_dc_ops
*dc_ops
;
34 static int kirin_drm_kms_cleanup(struct drm_device
*dev
)
36 drm_kms_helper_poll_fini(dev
);
37 dc_ops
->cleanup(to_platform_device(dev
->dev
));
38 drm_mode_config_cleanup(dev
);
43 static const struct drm_mode_config_funcs kirin_drm_mode_config_funcs
= {
44 .fb_create
= drm_gem_fb_create
,
45 .atomic_check
= drm_atomic_helper_check
,
46 .atomic_commit
= drm_atomic_helper_commit
,
49 static void kirin_drm_mode_config_init(struct drm_device
*dev
)
51 dev
->mode_config
.min_width
= 0;
52 dev
->mode_config
.min_height
= 0;
54 dev
->mode_config
.max_width
= 2048;
55 dev
->mode_config
.max_height
= 2048;
57 dev
->mode_config
.funcs
= &kirin_drm_mode_config_funcs
;
60 static int kirin_drm_kms_init(struct drm_device
*dev
)
64 dev_set_drvdata(dev
->dev
, dev
);
66 /* dev->mode_config initialization */
67 drm_mode_config_init(dev
);
68 kirin_drm_mode_config_init(dev
);
70 /* display controller init */
71 ret
= dc_ops
->init(to_platform_device(dev
->dev
));
73 goto err_mode_config_cleanup
;
75 /* bind and init sub drivers */
76 ret
= component_bind_all(dev
->dev
, dev
);
78 DRM_ERROR("failed to bind all component.\n");
83 ret
= drm_vblank_init(dev
, dev
->mode_config
.num_crtc
);
85 DRM_ERROR("failed to initialize vblank.\n");
88 /* with irq_enabled = true, we can use the vblank feature. */
89 dev
->irq_enabled
= true;
91 /* reset all the states of crtc/plane/encoder/connector */
92 drm_mode_config_reset(dev
);
94 /* init kms poll for handling hpd */
95 drm_kms_helper_poll_init(dev
);
100 component_unbind_all(dev
->dev
, dev
);
102 dc_ops
->cleanup(to_platform_device(dev
->dev
));
103 err_mode_config_cleanup
:
104 drm_mode_config_cleanup(dev
);
109 DEFINE_DRM_GEM_CMA_FOPS(kirin_drm_fops
);
111 static int kirin_gem_cma_dumb_create(struct drm_file
*file
,
112 struct drm_device
*dev
,
113 struct drm_mode_create_dumb
*args
)
115 return drm_gem_cma_dumb_create_internal(file
, dev
, args
);
118 static struct drm_driver kirin_drm_driver
= {
119 .driver_features
= DRIVER_GEM
| DRIVER_MODESET
| DRIVER_ATOMIC
,
120 .fops
= &kirin_drm_fops
,
122 .gem_free_object_unlocked
= drm_gem_cma_free_object
,
123 .gem_vm_ops
= &drm_gem_cma_vm_ops
,
124 .dumb_create
= kirin_gem_cma_dumb_create
,
126 .prime_handle_to_fd
= drm_gem_prime_handle_to_fd
,
127 .prime_fd_to_handle
= drm_gem_prime_fd_to_handle
,
128 .gem_prime_get_sg_table
= drm_gem_cma_prime_get_sg_table
,
129 .gem_prime_import_sg_table
= drm_gem_cma_prime_import_sg_table
,
130 .gem_prime_vmap
= drm_gem_cma_prime_vmap
,
131 .gem_prime_vunmap
= drm_gem_cma_prime_vunmap
,
132 .gem_prime_mmap
= drm_gem_cma_prime_mmap
,
135 .desc
= "Hisilicon Kirin SoCs' DRM Driver",
141 static int compare_of(struct device
*dev
, void *data
)
143 return dev
->of_node
== data
;
146 static int kirin_drm_bind(struct device
*dev
)
148 struct drm_driver
*driver
= &kirin_drm_driver
;
149 struct drm_device
*drm_dev
;
152 drm_dev
= drm_dev_alloc(driver
, dev
);
154 return PTR_ERR(drm_dev
);
156 ret
= kirin_drm_kms_init(drm_dev
);
158 goto err_drm_dev_put
;
160 ret
= drm_dev_register(drm_dev
, 0);
162 goto err_kms_cleanup
;
164 drm_fbdev_generic_setup(drm_dev
, 32);
169 kirin_drm_kms_cleanup(drm_dev
);
171 drm_dev_put(drm_dev
);
176 static void kirin_drm_unbind(struct device
*dev
)
178 struct drm_device
*drm_dev
= dev_get_drvdata(dev
);
180 drm_dev_unregister(drm_dev
);
181 kirin_drm_kms_cleanup(drm_dev
);
182 drm_dev_put(drm_dev
);
185 static const struct component_master_ops kirin_drm_ops
= {
186 .bind
= kirin_drm_bind
,
187 .unbind
= kirin_drm_unbind
,
190 static int kirin_drm_platform_probe(struct platform_device
*pdev
)
192 struct device
*dev
= &pdev
->dev
;
193 struct device_node
*np
= dev
->of_node
;
194 struct component_match
*match
= NULL
;
195 struct device_node
*remote
;
197 dc_ops
= (struct kirin_dc_ops
*)of_device_get_match_data(dev
);
199 DRM_ERROR("failed to get dt id data\n");
203 remote
= of_graph_get_remote_node(np
, 0, 0);
207 drm_of_component_match_add(dev
, &match
, compare_of
, remote
);
210 return component_master_add_with_match(dev
, &kirin_drm_ops
, match
);
215 static int kirin_drm_platform_remove(struct platform_device
*pdev
)
217 component_master_del(&pdev
->dev
, &kirin_drm_ops
);
222 static const struct of_device_id kirin_drm_dt_ids
[] = {
223 { .compatible
= "hisilicon,hi6220-ade",
228 MODULE_DEVICE_TABLE(of
, kirin_drm_dt_ids
);
230 static struct platform_driver kirin_drm_platform_driver
= {
231 .probe
= kirin_drm_platform_probe
,
232 .remove
= kirin_drm_platform_remove
,
235 .of_match_table
= kirin_drm_dt_ids
,
239 module_platform_driver(kirin_drm_platform_driver
);
241 MODULE_AUTHOR("Xinliang Liu <xinliang.liu@linaro.org>");
242 MODULE_AUTHOR("Xinliang Liu <z.liuxinliang@hisilicon.com>");
243 MODULE_AUTHOR("Xinwei Kong <kong.kongxinwei@hisilicon.com>");
244 MODULE_DESCRIPTION("hisilicon Kirin SoCs' DRM master driver");
245 MODULE_LICENSE("GPL v2");