1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) STMicroelectronics SA 2014
4 * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
9 #include <linux/component.h>
10 #include <linux/debugfs.h>
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/of_platform.h>
15 #include <drm/drm_atomic.h>
16 #include <drm/drm_atomic_helper.h>
17 #include <drm/drm_crtc_helper.h>
18 #include <drm/drm_gem_cma_helper.h>
19 #include <drm/drm_gem_framebuffer_helper.h>
20 #include <drm/drm_fb_helper.h>
21 #include <drm/drm_fb_cma_helper.h>
22 #include <drm/drm_of.h>
26 #include "sti_plane.h"
28 #define DRIVER_NAME "sti"
29 #define DRIVER_DESC "STMicroelectronics SoC DRM"
30 #define DRIVER_DATE "20140601"
31 #define DRIVER_MAJOR 1
32 #define DRIVER_MINOR 0
34 #define STI_MAX_FB_HEIGHT 4096
35 #define STI_MAX_FB_WIDTH 4096
37 static int sti_drm_fps_get(void *data
, u64
*val
)
39 struct drm_device
*drm_dev
= data
;
44 list_for_each_entry(p
, &drm_dev
->mode_config
.plane_list
, head
) {
45 struct sti_plane
*plane
= to_sti_plane(p
);
47 *val
|= plane
->fps_info
.output
<< i
;
54 static int sti_drm_fps_set(void *data
, u64 val
)
56 struct drm_device
*drm_dev
= data
;
60 list_for_each_entry(p
, &drm_dev
->mode_config
.plane_list
, head
) {
61 struct sti_plane
*plane
= to_sti_plane(p
);
63 memset(&plane
->fps_info
, 0, sizeof(plane
->fps_info
));
64 plane
->fps_info
.output
= (val
>> i
) & 1;
72 DEFINE_SIMPLE_ATTRIBUTE(sti_drm_fps_fops
,
73 sti_drm_fps_get
, sti_drm_fps_set
, "%llu\n");
75 static int sti_drm_fps_dbg_show(struct seq_file
*s
, void *data
)
77 struct drm_info_node
*node
= s
->private;
78 struct drm_device
*dev
= node
->minor
->dev
;
81 list_for_each_entry(p
, &dev
->mode_config
.plane_list
, head
) {
82 struct sti_plane
*plane
= to_sti_plane(p
);
84 seq_printf(s
, "%s%s\n",
85 plane
->fps_info
.fps_str
,
86 plane
->fps_info
.fips_str
);
92 static struct drm_info_list sti_drm_dbg_list
[] = {
93 {"fps_get", sti_drm_fps_dbg_show
, 0},
96 static int sti_drm_dbg_init(struct drm_minor
*minor
)
98 struct dentry
*dentry
;
101 ret
= drm_debugfs_create_files(sti_drm_dbg_list
,
102 ARRAY_SIZE(sti_drm_dbg_list
),
103 minor
->debugfs_root
, minor
);
107 dentry
= debugfs_create_file("fps_show", S_IRUGO
| S_IWUSR
,
108 minor
->debugfs_root
, minor
->dev
,
115 DRM_INFO("%s: debugfs installed\n", DRIVER_NAME
);
118 DRM_ERROR("%s: cannot install debugfs\n", DRIVER_NAME
);
122 static int sti_atomic_check(struct drm_device
*dev
,
123 struct drm_atomic_state
*state
)
127 ret
= drm_atomic_helper_check_modeset(dev
, state
);
131 ret
= drm_atomic_normalize_zpos(dev
, state
);
135 ret
= drm_atomic_helper_check_planes(dev
, state
);
142 static const struct drm_mode_config_funcs sti_mode_config_funcs
= {
143 .fb_create
= drm_gem_fb_create
,
144 .output_poll_changed
= drm_fb_helper_output_poll_changed
,
145 .atomic_check
= sti_atomic_check
,
146 .atomic_commit
= drm_atomic_helper_commit
,
149 static void sti_mode_config_init(struct drm_device
*dev
)
151 dev
->mode_config
.min_width
= 0;
152 dev
->mode_config
.min_height
= 0;
155 * set max width and height as default value.
156 * this value would be used to check framebuffer size limitation
157 * at drm_mode_addfb().
159 dev
->mode_config
.max_width
= STI_MAX_FB_WIDTH
;
160 dev
->mode_config
.max_height
= STI_MAX_FB_HEIGHT
;
162 dev
->mode_config
.funcs
= &sti_mode_config_funcs
;
165 DEFINE_DRM_GEM_CMA_FOPS(sti_driver_fops
);
167 static struct drm_driver sti_driver
= {
168 .driver_features
= DRIVER_MODESET
|
169 DRIVER_GEM
| DRIVER_PRIME
| DRIVER_ATOMIC
,
170 .gem_free_object_unlocked
= drm_gem_cma_free_object
,
171 .gem_vm_ops
= &drm_gem_cma_vm_ops
,
172 .dumb_create
= drm_gem_cma_dumb_create
,
173 .fops
= &sti_driver_fops
,
175 .enable_vblank
= sti_crtc_enable_vblank
,
176 .disable_vblank
= sti_crtc_disable_vblank
,
178 .prime_handle_to_fd
= drm_gem_prime_handle_to_fd
,
179 .prime_fd_to_handle
= drm_gem_prime_fd_to_handle
,
180 .gem_prime_export
= drm_gem_prime_export
,
181 .gem_prime_import
= drm_gem_prime_import
,
182 .gem_prime_get_sg_table
= drm_gem_cma_prime_get_sg_table
,
183 .gem_prime_import_sg_table
= drm_gem_cma_prime_import_sg_table
,
184 .gem_prime_vmap
= drm_gem_cma_prime_vmap
,
185 .gem_prime_vunmap
= drm_gem_cma_prime_vunmap
,
186 .gem_prime_mmap
= drm_gem_cma_prime_mmap
,
188 .debugfs_init
= sti_drm_dbg_init
,
193 .major
= DRIVER_MAJOR
,
194 .minor
= DRIVER_MINOR
,
197 static int compare_of(struct device
*dev
, void *data
)
199 return dev
->of_node
== data
;
202 static int sti_init(struct drm_device
*ddev
)
204 struct sti_private
*private;
206 private = kzalloc(sizeof(*private), GFP_KERNEL
);
210 ddev
->dev_private
= (void *)private;
211 dev_set_drvdata(ddev
->dev
, ddev
);
212 private->drm_dev
= ddev
;
214 drm_mode_config_init(ddev
);
216 sti_mode_config_init(ddev
);
218 drm_kms_helper_poll_init(ddev
);
223 static void sti_cleanup(struct drm_device
*ddev
)
225 struct sti_private
*private = ddev
->dev_private
;
227 drm_fb_cma_fbdev_fini(ddev
);
228 drm_kms_helper_poll_fini(ddev
);
229 component_unbind_all(ddev
->dev
, ddev
);
231 ddev
->dev_private
= NULL
;
234 static int sti_bind(struct device
*dev
)
236 struct drm_device
*ddev
;
239 ddev
= drm_dev_alloc(&sti_driver
, dev
);
241 return PTR_ERR(ddev
);
243 ret
= sti_init(ddev
);
245 goto err_drm_dev_unref
;
247 ret
= component_bind_all(ddev
->dev
, ddev
);
251 ret
= drm_dev_register(ddev
, 0);
255 drm_mode_config_reset(ddev
);
257 if (ddev
->mode_config
.num_connector
) {
258 ret
= drm_fb_cma_fbdev_init(ddev
, 32, 0);
260 DRM_DEBUG_DRIVER("Warning: fails to create fbdev\n");
266 drm_mode_config_cleanup(ddev
);
274 static void sti_unbind(struct device
*dev
)
276 struct drm_device
*ddev
= dev_get_drvdata(dev
);
278 drm_dev_unregister(ddev
);
283 static const struct component_master_ops sti_ops
= {
285 .unbind
= sti_unbind
,
288 static int sti_platform_probe(struct platform_device
*pdev
)
290 struct device
*dev
= &pdev
->dev
;
291 struct device_node
*node
= dev
->of_node
;
292 struct device_node
*child_np
;
293 struct component_match
*match
= NULL
;
295 dma_set_coherent_mask(dev
, DMA_BIT_MASK(32));
297 devm_of_platform_populate(dev
);
299 child_np
= of_get_next_available_child(node
, NULL
);
302 drm_of_component_match_add(dev
, &match
, compare_of
,
304 child_np
= of_get_next_available_child(node
, child_np
);
307 return component_master_add_with_match(dev
, &sti_ops
, match
);
310 static int sti_platform_remove(struct platform_device
*pdev
)
312 component_master_del(&pdev
->dev
, &sti_ops
);
317 static const struct of_device_id sti_dt_ids
[] = {
318 { .compatible
= "st,sti-display-subsystem", },
321 MODULE_DEVICE_TABLE(of
, sti_dt_ids
);
323 static struct platform_driver sti_platform_driver
= {
324 .probe
= sti_platform_probe
,
325 .remove
= sti_platform_remove
,
328 .of_match_table
= sti_dt_ids
,
332 static struct platform_driver
* const drivers
[] = {
339 &sti_compositor_driver
,
340 &sti_platform_driver
,
343 static int sti_drm_init(void)
345 return platform_register_drivers(drivers
, ARRAY_SIZE(drivers
));
347 module_init(sti_drm_init
);
349 static void sti_drm_exit(void)
351 platform_unregister_drivers(drivers
, ARRAY_SIZE(drivers
));
353 module_exit(sti_drm_exit
);
355 MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
356 MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
357 MODULE_LICENSE("GPL");