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
|
172 DRIVER_ATOMIC
| DRIVER_HAVE_IRQ
,
173 .fops
= &kirin_drm_fops
,
174 .set_busid
= drm_platform_set_busid
,
176 .gem_free_object
= drm_gem_cma_free_object
,
177 .gem_vm_ops
= &drm_gem_cma_vm_ops
,
178 .dumb_create
= kirin_gem_cma_dumb_create
,
179 .dumb_map_offset
= drm_gem_cma_dumb_map_offset
,
180 .dumb_destroy
= drm_gem_dumb_destroy
,
182 .prime_handle_to_fd
= drm_gem_prime_handle_to_fd
,
183 .prime_fd_to_handle
= drm_gem_prime_fd_to_handle
,
184 .gem_prime_export
= drm_gem_prime_export
,
185 .gem_prime_import
= drm_gem_prime_import
,
186 .gem_prime_get_sg_table
= drm_gem_cma_prime_get_sg_table
,
187 .gem_prime_import_sg_table
= drm_gem_cma_prime_import_sg_table
,
188 .gem_prime_vmap
= drm_gem_cma_prime_vmap
,
189 .gem_prime_vunmap
= drm_gem_cma_prime_vunmap
,
190 .gem_prime_mmap
= drm_gem_cma_prime_mmap
,
193 .desc
= "Hisilicon Kirin SoCs' DRM Driver",
199 static int compare_of(struct device
*dev
, void *data
)
201 return dev
->of_node
== data
;
204 static int kirin_drm_bind(struct device
*dev
)
206 struct drm_driver
*driver
= &kirin_drm_driver
;
207 struct drm_device
*drm_dev
;
210 drm_dev
= drm_dev_alloc(driver
, dev
);
214 drm_dev
->platformdev
= to_platform_device(dev
);
216 ret
= kirin_drm_kms_init(drm_dev
);
218 goto err_drm_dev_unref
;
220 ret
= drm_dev_register(drm_dev
, 0);
222 goto err_kms_cleanup
;
224 /* connectors should be registered after drm device register */
225 ret
= drm_connector_register_all(drm_dev
);
227 goto err_drm_dev_unregister
;
229 DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
230 driver
->name
, driver
->major
, driver
->minor
, driver
->patchlevel
,
231 driver
->date
, drm_dev
->primary
->index
);
235 err_drm_dev_unregister
:
236 drm_dev_unregister(drm_dev
);
238 kirin_drm_kms_cleanup(drm_dev
);
240 drm_dev_unref(drm_dev
);
245 static void kirin_drm_unbind(struct device
*dev
)
247 struct drm_device
*drm_dev
= dev_get_drvdata(dev
);
249 drm_connector_unregister_all(drm_dev
);
250 drm_dev_unregister(drm_dev
);
251 kirin_drm_kms_cleanup(drm_dev
);
252 drm_dev_unref(drm_dev
);
255 static const struct component_master_ops kirin_drm_ops
= {
256 .bind
= kirin_drm_bind
,
257 .unbind
= kirin_drm_unbind
,
260 static struct device_node
*kirin_get_remote_node(struct device_node
*np
)
262 struct device_node
*endpoint
, *remote
;
264 /* get the first endpoint, in our case only one remote node
265 * is connected to display controller.
267 endpoint
= of_graph_get_next_endpoint(np
, NULL
);
269 DRM_ERROR("no valid endpoint node\n");
270 return ERR_PTR(-ENODEV
);
272 of_node_put(endpoint
);
274 remote
= of_graph_get_remote_port_parent(endpoint
);
276 DRM_ERROR("no valid remote node\n");
277 return ERR_PTR(-ENODEV
);
281 if (!of_device_is_available(remote
)) {
282 DRM_ERROR("not available for remote node\n");
283 return ERR_PTR(-ENODEV
);
289 static int kirin_drm_platform_probe(struct platform_device
*pdev
)
291 struct device
*dev
= &pdev
->dev
;
292 struct device_node
*np
= dev
->of_node
;
293 struct component_match
*match
= NULL
;
294 struct device_node
*remote
;
296 dc_ops
= (struct kirin_dc_ops
*)of_device_get_match_data(dev
);
298 DRM_ERROR("failed to get dt id data\n");
302 remote
= kirin_get_remote_node(np
);
304 return PTR_ERR(remote
);
306 component_match_add(dev
, &match
, compare_of
, remote
);
308 return component_master_add_with_match(dev
, &kirin_drm_ops
, match
);
313 static int kirin_drm_platform_remove(struct platform_device
*pdev
)
315 component_master_del(&pdev
->dev
, &kirin_drm_ops
);
320 static const struct of_device_id kirin_drm_dt_ids
[] = {
321 { .compatible
= "hisilicon,hi6220-ade",
326 MODULE_DEVICE_TABLE(of
, kirin_drm_dt_ids
);
328 static struct platform_driver kirin_drm_platform_driver
= {
329 .probe
= kirin_drm_platform_probe
,
330 .remove
= kirin_drm_platform_remove
,
333 .of_match_table
= kirin_drm_dt_ids
,
337 module_platform_driver(kirin_drm_platform_driver
);
339 MODULE_AUTHOR("Xinliang Liu <xinliang.liu@linaro.org>");
340 MODULE_AUTHOR("Xinliang Liu <z.liuxinliang@hisilicon.com>");
341 MODULE_AUTHOR("Xinwei Kong <kong.kongxinwei@hisilicon.com>");
342 MODULE_DESCRIPTION("hisilicon Kirin SoCs' DRM master driver");
343 MODULE_LICENSE("GPL v2");