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_atomic_helper.h>
26 #include <drm/drm_crtc_helper.h>
28 #include "kirin_drm_drv.h"
30 static struct kirin_dc_ops
*dc_ops
;
32 static int kirin_drm_kms_cleanup(struct drm_device
*dev
)
34 struct kirin_drm_private
*priv
= dev
->dev_private
;
36 #ifdef CONFIG_DRM_FBDEV_EMULATION
38 drm_fbdev_cma_fini(priv
->fbdev
);
42 drm_kms_helper_poll_fini(dev
);
43 drm_vblank_cleanup(dev
);
45 drm_mode_config_cleanup(dev
);
46 devm_kfree(dev
->dev
, priv
);
47 dev
->dev_private
= NULL
;
52 #ifdef CONFIG_DRM_FBDEV_EMULATION
53 static void kirin_fbdev_output_poll_changed(struct drm_device
*dev
)
55 struct kirin_drm_private
*priv
= dev
->dev_private
;
58 drm_fbdev_cma_hotplug_event(priv
->fbdev
);
60 priv
->fbdev
= drm_fbdev_cma_init(dev
, 32,
61 dev
->mode_config
.num_crtc
,
62 dev
->mode_config
.num_connector
);
63 if (IS_ERR(priv
->fbdev
))
69 static const struct drm_mode_config_funcs kirin_drm_mode_config_funcs
= {
70 .fb_create
= drm_fb_cma_create
,
71 #ifdef CONFIG_DRM_FBDEV_EMULATION
72 .output_poll_changed
= kirin_fbdev_output_poll_changed
,
74 .atomic_check
= drm_atomic_helper_check
,
75 .atomic_commit
= drm_atomic_helper_commit
,
78 static void kirin_drm_mode_config_init(struct drm_device
*dev
)
80 dev
->mode_config
.min_width
= 0;
81 dev
->mode_config
.min_height
= 0;
83 dev
->mode_config
.max_width
= 2048;
84 dev
->mode_config
.max_height
= 2048;
86 dev
->mode_config
.funcs
= &kirin_drm_mode_config_funcs
;
89 static int kirin_drm_kms_init(struct drm_device
*dev
)
91 struct kirin_drm_private
*priv
;
94 priv
= devm_kzalloc(dev
->dev
, sizeof(*priv
), GFP_KERNEL
);
98 dev
->dev_private
= priv
;
99 dev_set_drvdata(dev
->dev
, dev
);
101 /* dev->mode_config initialization */
102 drm_mode_config_init(dev
);
103 kirin_drm_mode_config_init(dev
);
105 /* display controller init */
106 ret
= dc_ops
->init(dev
);
108 goto err_mode_config_cleanup
;
110 /* bind and init sub drivers */
111 ret
= component_bind_all(dev
->dev
, dev
);
113 DRM_ERROR("failed to bind all component.\n");
118 ret
= drm_vblank_init(dev
, dev
->mode_config
.num_crtc
);
120 DRM_ERROR("failed to initialize vblank.\n");
123 /* with irq_enabled = true, we can use the vblank feature. */
124 dev
->irq_enabled
= true;
126 /* reset all the states of crtc/plane/encoder/connector */
127 drm_mode_config_reset(dev
);
129 /* init kms poll for handling hpd */
130 drm_kms_helper_poll_init(dev
);
132 /* force detection after connectors init */
133 (void)drm_helper_hpd_irq_event(dev
);
138 component_unbind_all(dev
->dev
, dev
);
140 dc_ops
->cleanup(dev
);
141 err_mode_config_cleanup
:
142 drm_mode_config_cleanup(dev
);
143 devm_kfree(dev
->dev
, priv
);
144 dev
->dev_private
= NULL
;
149 static const struct file_operations kirin_drm_fops
= {
150 .owner
= THIS_MODULE
,
152 .release
= drm_release
,
153 .unlocked_ioctl
= drm_ioctl
,
155 .compat_ioctl
= drm_compat_ioctl
,
160 .mmap
= drm_gem_cma_mmap
,
163 static int kirin_gem_cma_dumb_create(struct drm_file
*file
,
164 struct drm_device
*dev
,
165 struct drm_mode_create_dumb
*args
)
167 return drm_gem_cma_dumb_create_internal(file
, dev
, args
);
170 static struct drm_driver kirin_drm_driver
= {
171 .driver_features
= DRIVER_GEM
| DRIVER_MODESET
| DRIVER_PRIME
|
173 .fops
= &kirin_drm_fops
,
175 .gem_free_object_unlocked
= drm_gem_cma_free_object
,
176 .gem_vm_ops
= &drm_gem_cma_vm_ops
,
177 .dumb_create
= kirin_gem_cma_dumb_create
,
178 .dumb_map_offset
= drm_gem_cma_dumb_map_offset
,
179 .dumb_destroy
= drm_gem_dumb_destroy
,
181 .prime_handle_to_fd
= drm_gem_prime_handle_to_fd
,
182 .prime_fd_to_handle
= drm_gem_prime_fd_to_handle
,
183 .gem_prime_export
= drm_gem_prime_export
,
184 .gem_prime_import
= drm_gem_prime_import
,
185 .gem_prime_get_sg_table
= drm_gem_cma_prime_get_sg_table
,
186 .gem_prime_import_sg_table
= drm_gem_cma_prime_import_sg_table
,
187 .gem_prime_vmap
= drm_gem_cma_prime_vmap
,
188 .gem_prime_vunmap
= drm_gem_cma_prime_vunmap
,
189 .gem_prime_mmap
= drm_gem_cma_prime_mmap
,
192 .desc
= "Hisilicon Kirin SoCs' DRM Driver",
198 static int compare_of(struct device
*dev
, void *data
)
200 return dev
->of_node
== data
;
203 static int kirin_drm_bind(struct device
*dev
)
205 struct drm_driver
*driver
= &kirin_drm_driver
;
206 struct drm_device
*drm_dev
;
209 drm_dev
= drm_dev_alloc(driver
, dev
);
211 return PTR_ERR(drm_dev
);
213 drm_dev
->platformdev
= to_platform_device(dev
);
215 ret
= kirin_drm_kms_init(drm_dev
);
217 goto err_drm_dev_unref
;
219 ret
= drm_dev_register(drm_dev
, 0);
221 goto err_kms_cleanup
;
223 DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
224 driver
->name
, driver
->major
, driver
->minor
, driver
->patchlevel
,
225 driver
->date
, drm_dev
->primary
->index
);
230 kirin_drm_kms_cleanup(drm_dev
);
232 drm_dev_unref(drm_dev
);
237 static void kirin_drm_unbind(struct device
*dev
)
239 struct drm_device
*drm_dev
= dev_get_drvdata(dev
);
241 drm_dev_unregister(drm_dev
);
242 kirin_drm_kms_cleanup(drm_dev
);
243 drm_dev_unref(drm_dev
);
246 static const struct component_master_ops kirin_drm_ops
= {
247 .bind
= kirin_drm_bind
,
248 .unbind
= kirin_drm_unbind
,
251 static struct device_node
*kirin_get_remote_node(struct device_node
*np
)
253 struct device_node
*endpoint
, *remote
;
255 /* get the first endpoint, in our case only one remote node
256 * is connected to display controller.
258 endpoint
= of_graph_get_next_endpoint(np
, NULL
);
260 DRM_ERROR("no valid endpoint node\n");
261 return ERR_PTR(-ENODEV
);
263 of_node_put(endpoint
);
265 remote
= of_graph_get_remote_port_parent(endpoint
);
267 DRM_ERROR("no valid remote node\n");
268 return ERR_PTR(-ENODEV
);
272 if (!of_device_is_available(remote
)) {
273 DRM_ERROR("not available for remote node\n");
274 return ERR_PTR(-ENODEV
);
280 static int kirin_drm_platform_probe(struct platform_device
*pdev
)
282 struct device
*dev
= &pdev
->dev
;
283 struct device_node
*np
= dev
->of_node
;
284 struct component_match
*match
= NULL
;
285 struct device_node
*remote
;
287 dc_ops
= (struct kirin_dc_ops
*)of_device_get_match_data(dev
);
289 DRM_ERROR("failed to get dt id data\n");
293 remote
= kirin_get_remote_node(np
);
295 return PTR_ERR(remote
);
297 component_match_add(dev
, &match
, compare_of
, remote
);
299 return component_master_add_with_match(dev
, &kirin_drm_ops
, match
);
304 static int kirin_drm_platform_remove(struct platform_device
*pdev
)
306 component_master_del(&pdev
->dev
, &kirin_drm_ops
);
311 static const struct of_device_id kirin_drm_dt_ids
[] = {
312 { .compatible
= "hisilicon,hi6220-ade",
317 MODULE_DEVICE_TABLE(of
, kirin_drm_dt_ids
);
319 static struct platform_driver kirin_drm_platform_driver
= {
320 .probe
= kirin_drm_platform_probe
,
321 .remove
= kirin_drm_platform_remove
,
324 .of_match_table
= kirin_drm_dt_ids
,
328 module_platform_driver(kirin_drm_platform_driver
);
330 MODULE_AUTHOR("Xinliang Liu <xinliang.liu@linaro.org>");
331 MODULE_AUTHOR("Xinliang Liu <z.liuxinliang@hisilicon.com>");
332 MODULE_AUTHOR("Xinwei Kong <kong.kongxinwei@hisilicon.com>");
333 MODULE_DESCRIPTION("hisilicon Kirin SoCs' DRM master driver");
334 MODULE_LICENSE("GPL v2");