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 #define KIRIN_MAX_PLANE 2
34 struct kirin_drm_private
{
35 struct kirin_crtc crtc
;
36 struct kirin_plane planes
[KIRIN_MAX_PLANE
];
40 static int kirin_drm_crtc_init(struct drm_device
*dev
, struct drm_crtc
*crtc
,
41 struct drm_plane
*plane
,
42 const struct kirin_drm_data
*driver_data
)
44 struct device_node
*port
;
47 /* set crtc port so that
48 * drm_of_find_possible_crtcs call works
50 port
= of_get_child_by_name(dev
->dev
->of_node
, "port");
52 DRM_ERROR("no port node found in %pOF\n", dev
->dev
->of_node
);
58 ret
= drm_crtc_init_with_planes(dev
, crtc
, plane
, NULL
,
59 driver_data
->crtc_funcs
, NULL
);
61 DRM_ERROR("failed to init crtc.\n");
65 drm_crtc_helper_add(crtc
, driver_data
->crtc_helper_funcs
);
70 static int kirin_drm_plane_init(struct drm_device
*dev
, struct drm_plane
*plane
,
71 enum drm_plane_type type
,
72 const struct kirin_drm_data
*data
)
76 ret
= drm_universal_plane_init(dev
, plane
, 1, data
->plane_funcs
,
77 data
->channel_formats
,
78 data
->channel_formats_cnt
,
81 DRM_ERROR("fail to init plane, ch=%d\n", 0);
85 drm_plane_helper_add(plane
, data
->plane_helper_funcs
);
90 static void kirin_drm_private_cleanup(struct drm_device
*dev
)
92 struct kirin_drm_private
*kirin_priv
= dev
->dev_private
;
93 struct kirin_drm_data
*data
;
95 data
= (struct kirin_drm_data
*)of_device_get_match_data(dev
->dev
);
96 if (data
->cleanup_hw_ctx
)
97 data
->cleanup_hw_ctx(kirin_priv
->hw_ctx
);
99 devm_kfree(dev
->dev
, kirin_priv
);
100 dev
->dev_private
= NULL
;
103 static int kirin_drm_private_init(struct drm_device
*dev
,
104 const struct kirin_drm_data
*driver_data
)
106 struct platform_device
*pdev
= to_platform_device(dev
->dev
);
107 struct kirin_drm_private
*kirin_priv
;
108 struct drm_plane
*prim_plane
;
109 enum drm_plane_type type
;
114 kirin_priv
= devm_kzalloc(dev
->dev
, sizeof(*kirin_priv
), GFP_KERNEL
);
116 DRM_ERROR("failed to alloc kirin_drm_private\n");
120 ctx
= driver_data
->alloc_hw_ctx(pdev
, &kirin_priv
->crtc
.base
);
122 DRM_ERROR("failed to initialize kirin_priv hw ctx\n");
125 kirin_priv
->hw_ctx
= ctx
;
129 * TODO: Now only support primary plane, overlay planes
132 for (ch
= 0; ch
< driver_data
->num_planes
; ch
++) {
133 if (ch
== driver_data
->prim_plane
)
134 type
= DRM_PLANE_TYPE_PRIMARY
;
136 type
= DRM_PLANE_TYPE_OVERLAY
;
137 ret
= kirin_drm_plane_init(dev
, &kirin_priv
->planes
[ch
].base
,
141 kirin_priv
->planes
[ch
].ch
= ch
;
142 kirin_priv
->planes
[ch
].hw_ctx
= ctx
;
146 prim_plane
= &kirin_priv
->planes
[driver_data
->prim_plane
].base
;
147 ret
= kirin_drm_crtc_init(dev
, &kirin_priv
->crtc
.base
,
148 prim_plane
, driver_data
);
151 kirin_priv
->crtc
.hw_ctx
= ctx
;
152 dev
->dev_private
= kirin_priv
;
157 static int kirin_drm_kms_init(struct drm_device
*dev
,
158 const struct kirin_drm_data
*driver_data
)
162 /* dev->mode_config initialization */
163 drm_mode_config_init(dev
);
164 dev
->mode_config
.min_width
= 0;
165 dev
->mode_config
.min_height
= 0;
166 dev
->mode_config
.max_width
= driver_data
->config_max_width
;
167 dev
->mode_config
.max_height
= driver_data
->config_max_width
;
168 dev
->mode_config
.funcs
= driver_data
->mode_config_funcs
;
170 /* display controller init */
171 ret
= kirin_drm_private_init(dev
, driver_data
);
173 goto err_mode_config_cleanup
;
175 /* bind and init sub drivers */
176 ret
= component_bind_all(dev
->dev
, dev
);
178 DRM_ERROR("failed to bind all component.\n");
179 goto err_private_cleanup
;
183 ret
= drm_vblank_init(dev
, dev
->mode_config
.num_crtc
);
185 DRM_ERROR("failed to initialize vblank.\n");
188 /* with irq_enabled = true, we can use the vblank feature. */
189 dev
->irq_enabled
= true;
191 /* reset all the states of crtc/plane/encoder/connector */
192 drm_mode_config_reset(dev
);
194 /* init kms poll for handling hpd */
195 drm_kms_helper_poll_init(dev
);
200 component_unbind_all(dev
->dev
, dev
);
202 kirin_drm_private_cleanup(dev
);
203 err_mode_config_cleanup
:
204 drm_mode_config_cleanup(dev
);
208 static int compare_of(struct device
*dev
, void *data
)
210 return dev
->of_node
== data
;
213 static int kirin_drm_kms_cleanup(struct drm_device
*dev
)
215 drm_kms_helper_poll_fini(dev
);
216 kirin_drm_private_cleanup(dev
);
217 drm_mode_config_cleanup(dev
);
222 static int kirin_drm_bind(struct device
*dev
)
224 struct kirin_drm_data
*driver_data
;
225 struct drm_device
*drm_dev
;
228 driver_data
= (struct kirin_drm_data
*)of_device_get_match_data(dev
);
232 drm_dev
= drm_dev_alloc(driver_data
->driver
, dev
);
234 return PTR_ERR(drm_dev
);
235 dev_set_drvdata(dev
, drm_dev
);
237 /* display controller init */
238 ret
= kirin_drm_kms_init(drm_dev
, driver_data
);
240 goto err_drm_dev_put
;
242 ret
= drm_dev_register(drm_dev
, 0);
244 goto err_kms_cleanup
;
246 drm_fbdev_generic_setup(drm_dev
, 32);
251 kirin_drm_kms_cleanup(drm_dev
);
253 drm_dev_put(drm_dev
);
258 static void kirin_drm_unbind(struct device
*dev
)
260 struct drm_device
*drm_dev
= dev_get_drvdata(dev
);
262 drm_dev_unregister(drm_dev
);
263 kirin_drm_kms_cleanup(drm_dev
);
264 drm_dev_put(drm_dev
);
267 static const struct component_master_ops kirin_drm_ops
= {
268 .bind
= kirin_drm_bind
,
269 .unbind
= kirin_drm_unbind
,
272 static int kirin_drm_platform_probe(struct platform_device
*pdev
)
274 struct device
*dev
= &pdev
->dev
;
275 struct device_node
*np
= dev
->of_node
;
276 struct component_match
*match
= NULL
;
277 struct device_node
*remote
;
279 remote
= of_graph_get_remote_node(np
, 0, 0);
283 drm_of_component_match_add(dev
, &match
, compare_of
, remote
);
286 return component_master_add_with_match(dev
, &kirin_drm_ops
, match
);
289 static int kirin_drm_platform_remove(struct platform_device
*pdev
)
291 component_master_del(&pdev
->dev
, &kirin_drm_ops
);
295 static const struct of_device_id kirin_drm_dt_ids
[] = {
296 { .compatible
= "hisilicon,hi6220-ade",
297 .data
= &ade_driver_data
,
301 MODULE_DEVICE_TABLE(of
, kirin_drm_dt_ids
);
303 static struct platform_driver kirin_drm_platform_driver
= {
304 .probe
= kirin_drm_platform_probe
,
305 .remove
= kirin_drm_platform_remove
,
308 .of_match_table
= kirin_drm_dt_ids
,
312 module_platform_driver(kirin_drm_platform_driver
);
314 MODULE_AUTHOR("Xinliang Liu <xinliang.liu@linaro.org>");
315 MODULE_AUTHOR("Xinliang Liu <z.liuxinliang@hisilicon.com>");
316 MODULE_AUTHOR("Xinwei Kong <kong.kongxinwei@hisilicon.com>");
317 MODULE_DESCRIPTION("hisilicon Kirin SoCs' DRM master driver");
318 MODULE_LICENSE("GPL v2");