2 * Hisilicon Kirin SoCs drm master driver
4 * Copyright (c) 2016 Linaro Limited.
5 * Copyright (c) 2014-2016 Hisilicon Limited.
8 * Xinliang Liu <z.liuxinliang@hisilicon.com>
9 * Xinliang Liu <xinliang.liu@linaro.org>
10 * Xinwei Kong <kong.kongxinwei@hisilicon.com>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
18 #include <linux/of_platform.h>
19 #include <linux/component.h>
20 #include <linux/of_graph.h>
23 #include <drm/drm_gem_cma_helper.h>
24 #include <drm/drm_fb_cma_helper.h>
25 #include <drm/drm_gem_framebuffer_helper.h>
26 #include <drm/drm_atomic_helper.h>
27 #include <drm/drm_crtc_helper.h>
28 #include <drm/drm_of.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 struct kirin_drm_private
*priv
= dev
->dev_private
;
39 drm_fbdev_cma_fini(priv
->fbdev
);
43 drm_kms_helper_poll_fini(dev
);
44 dc_ops
->cleanup(to_platform_device(dev
->dev
));
45 drm_mode_config_cleanup(dev
);
46 devm_kfree(dev
->dev
, priv
);
47 dev
->dev_private
= NULL
;
52 static void kirin_fbdev_output_poll_changed(struct drm_device
*dev
)
54 struct kirin_drm_private
*priv
= dev
->dev_private
;
56 drm_fbdev_cma_hotplug_event(priv
->fbdev
);
59 static const struct drm_mode_config_funcs kirin_drm_mode_config_funcs
= {
60 .fb_create
= drm_gem_fb_create
,
61 .output_poll_changed
= kirin_fbdev_output_poll_changed
,
62 .atomic_check
= drm_atomic_helper_check
,
63 .atomic_commit
= drm_atomic_helper_commit
,
66 static void kirin_drm_mode_config_init(struct drm_device
*dev
)
68 dev
->mode_config
.min_width
= 0;
69 dev
->mode_config
.min_height
= 0;
71 dev
->mode_config
.max_width
= 2048;
72 dev
->mode_config
.max_height
= 2048;
74 dev
->mode_config
.funcs
= &kirin_drm_mode_config_funcs
;
77 static int kirin_drm_kms_init(struct drm_device
*dev
)
79 struct kirin_drm_private
*priv
;
82 priv
= devm_kzalloc(dev
->dev
, sizeof(*priv
), GFP_KERNEL
);
86 dev
->dev_private
= priv
;
87 dev_set_drvdata(dev
->dev
, dev
);
89 /* dev->mode_config initialization */
90 drm_mode_config_init(dev
);
91 kirin_drm_mode_config_init(dev
);
93 /* display controller init */
94 ret
= dc_ops
->init(to_platform_device(dev
->dev
));
96 goto err_mode_config_cleanup
;
98 /* bind and init sub drivers */
99 ret
= component_bind_all(dev
->dev
, dev
);
101 DRM_ERROR("failed to bind all component.\n");
106 ret
= drm_vblank_init(dev
, dev
->mode_config
.num_crtc
);
108 DRM_ERROR("failed to initialize vblank.\n");
111 /* with irq_enabled = true, we can use the vblank feature. */
112 dev
->irq_enabled
= true;
114 /* reset all the states of crtc/plane/encoder/connector */
115 drm_mode_config_reset(dev
);
117 /* init kms poll for handling hpd */
118 drm_kms_helper_poll_init(dev
);
120 priv
->fbdev
= drm_fbdev_cma_init(dev
, 32,
121 dev
->mode_config
.num_connector
);
123 if (IS_ERR(priv
->fbdev
)) {
124 DRM_ERROR("failed to initialize fbdev.\n");
125 ret
= PTR_ERR(priv
->fbdev
);
126 goto err_cleanup_poll
;
131 drm_kms_helper_poll_fini(dev
);
133 component_unbind_all(dev
->dev
, dev
);
135 dc_ops
->cleanup(to_platform_device(dev
->dev
));
136 err_mode_config_cleanup
:
137 drm_mode_config_cleanup(dev
);
138 devm_kfree(dev
->dev
, priv
);
139 dev
->dev_private
= NULL
;
144 DEFINE_DRM_GEM_CMA_FOPS(kirin_drm_fops
);
146 static int kirin_gem_cma_dumb_create(struct drm_file
*file
,
147 struct drm_device
*dev
,
148 struct drm_mode_create_dumb
*args
)
150 return drm_gem_cma_dumb_create_internal(file
, dev
, args
);
153 static struct drm_driver kirin_drm_driver
= {
154 .driver_features
= DRIVER_GEM
| DRIVER_MODESET
| DRIVER_PRIME
|
156 .fops
= &kirin_drm_fops
,
158 .gem_free_object_unlocked
= drm_gem_cma_free_object
,
159 .gem_vm_ops
= &drm_gem_cma_vm_ops
,
160 .dumb_create
= kirin_gem_cma_dumb_create
,
162 .prime_handle_to_fd
= drm_gem_prime_handle_to_fd
,
163 .prime_fd_to_handle
= drm_gem_prime_fd_to_handle
,
164 .gem_prime_export
= drm_gem_prime_export
,
165 .gem_prime_import
= drm_gem_prime_import
,
166 .gem_prime_get_sg_table
= drm_gem_cma_prime_get_sg_table
,
167 .gem_prime_import_sg_table
= drm_gem_cma_prime_import_sg_table
,
168 .gem_prime_vmap
= drm_gem_cma_prime_vmap
,
169 .gem_prime_vunmap
= drm_gem_cma_prime_vunmap
,
170 .gem_prime_mmap
= drm_gem_cma_prime_mmap
,
173 .desc
= "Hisilicon Kirin SoCs' DRM Driver",
179 static int compare_of(struct device
*dev
, void *data
)
181 return dev
->of_node
== data
;
184 static int kirin_drm_bind(struct device
*dev
)
186 struct drm_driver
*driver
= &kirin_drm_driver
;
187 struct drm_device
*drm_dev
;
190 drm_dev
= drm_dev_alloc(driver
, dev
);
192 return PTR_ERR(drm_dev
);
194 ret
= kirin_drm_kms_init(drm_dev
);
196 goto err_drm_dev_unref
;
198 ret
= drm_dev_register(drm_dev
, 0);
200 goto err_kms_cleanup
;
205 kirin_drm_kms_cleanup(drm_dev
);
207 drm_dev_unref(drm_dev
);
212 static void kirin_drm_unbind(struct device
*dev
)
214 struct drm_device
*drm_dev
= dev_get_drvdata(dev
);
216 drm_dev_unregister(drm_dev
);
217 kirin_drm_kms_cleanup(drm_dev
);
218 drm_dev_unref(drm_dev
);
221 static const struct component_master_ops kirin_drm_ops
= {
222 .bind
= kirin_drm_bind
,
223 .unbind
= kirin_drm_unbind
,
226 static int kirin_drm_platform_probe(struct platform_device
*pdev
)
228 struct device
*dev
= &pdev
->dev
;
229 struct device_node
*np
= dev
->of_node
;
230 struct component_match
*match
= NULL
;
231 struct device_node
*remote
;
233 dc_ops
= (struct kirin_dc_ops
*)of_device_get_match_data(dev
);
235 DRM_ERROR("failed to get dt id data\n");
239 remote
= of_graph_get_remote_node(np
, 0, 0);
243 drm_of_component_match_add(dev
, &match
, compare_of
, remote
);
246 return component_master_add_with_match(dev
, &kirin_drm_ops
, match
);
251 static int kirin_drm_platform_remove(struct platform_device
*pdev
)
253 component_master_del(&pdev
->dev
, &kirin_drm_ops
);
258 static const struct of_device_id kirin_drm_dt_ids
[] = {
259 { .compatible
= "hisilicon,hi6220-ade",
264 MODULE_DEVICE_TABLE(of
, kirin_drm_dt_ids
);
266 static struct platform_driver kirin_drm_platform_driver
= {
267 .probe
= kirin_drm_platform_probe
,
268 .remove
= kirin_drm_platform_remove
,
271 .of_match_table
= kirin_drm_dt_ids
,
275 module_platform_driver(kirin_drm_platform_driver
);
277 MODULE_AUTHOR("Xinliang Liu <xinliang.liu@linaro.org>");
278 MODULE_AUTHOR("Xinliang Liu <z.liuxinliang@hisilicon.com>");
279 MODULE_AUTHOR("Xinwei Kong <kong.kongxinwei@hisilicon.com>");
280 MODULE_DESCRIPTION("hisilicon Kirin SoCs' DRM master driver");
281 MODULE_LICENSE("GPL v2");