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_gem_cma_helper.h>
18 #include <drm/drm_gem_framebuffer_helper.h>
19 #include <drm/drm_fb_helper.h>
20 #include <drm/drm_fb_cma_helper.h>
21 #include <drm/drm_of.h>
22 #include <drm/drm_probe_helper.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 const struct drm_mode_config_funcs sti_mode_config_funcs
= {
123 .fb_create
= drm_gem_fb_create
,
124 .atomic_check
= drm_atomic_helper_check
,
125 .atomic_commit
= drm_atomic_helper_commit
,
128 static void sti_mode_config_init(struct drm_device
*dev
)
130 dev
->mode_config
.min_width
= 0;
131 dev
->mode_config
.min_height
= 0;
134 * set max width and height as default value.
135 * this value would be used to check framebuffer size limitation
136 * at drm_mode_addfb().
138 dev
->mode_config
.max_width
= STI_MAX_FB_WIDTH
;
139 dev
->mode_config
.max_height
= STI_MAX_FB_HEIGHT
;
141 dev
->mode_config
.funcs
= &sti_mode_config_funcs
;
143 dev
->mode_config
.normalize_zpos
= true;
146 DEFINE_DRM_GEM_CMA_FOPS(sti_driver_fops
);
148 static struct drm_driver sti_driver
= {
149 .driver_features
= DRIVER_MODESET
|
150 DRIVER_GEM
| DRIVER_PRIME
| DRIVER_ATOMIC
,
151 .gem_free_object_unlocked
= drm_gem_cma_free_object
,
152 .gem_vm_ops
= &drm_gem_cma_vm_ops
,
153 .dumb_create
= drm_gem_cma_dumb_create
,
154 .fops
= &sti_driver_fops
,
156 .enable_vblank
= sti_crtc_enable_vblank
,
157 .disable_vblank
= sti_crtc_disable_vblank
,
159 .prime_handle_to_fd
= drm_gem_prime_handle_to_fd
,
160 .prime_fd_to_handle
= drm_gem_prime_fd_to_handle
,
161 .gem_prime_export
= drm_gem_prime_export
,
162 .gem_prime_import
= drm_gem_prime_import
,
163 .gem_prime_get_sg_table
= drm_gem_cma_prime_get_sg_table
,
164 .gem_prime_import_sg_table
= drm_gem_cma_prime_import_sg_table
,
165 .gem_prime_vmap
= drm_gem_cma_prime_vmap
,
166 .gem_prime_vunmap
= drm_gem_cma_prime_vunmap
,
167 .gem_prime_mmap
= drm_gem_cma_prime_mmap
,
169 .debugfs_init
= sti_drm_dbg_init
,
174 .major
= DRIVER_MAJOR
,
175 .minor
= DRIVER_MINOR
,
178 static int compare_of(struct device
*dev
, void *data
)
180 return dev
->of_node
== data
;
183 static int sti_init(struct drm_device
*ddev
)
185 struct sti_private
*private;
187 private = kzalloc(sizeof(*private), GFP_KERNEL
);
191 ddev
->dev_private
= (void *)private;
192 dev_set_drvdata(ddev
->dev
, ddev
);
193 private->drm_dev
= ddev
;
195 drm_mode_config_init(ddev
);
197 sti_mode_config_init(ddev
);
199 drm_kms_helper_poll_init(ddev
);
204 static void sti_cleanup(struct drm_device
*ddev
)
206 struct sti_private
*private = ddev
->dev_private
;
208 drm_kms_helper_poll_fini(ddev
);
209 drm_atomic_helper_shutdown(ddev
);
210 drm_mode_config_cleanup(ddev
);
211 component_unbind_all(ddev
->dev
, ddev
);
213 ddev
->dev_private
= NULL
;
216 static int sti_bind(struct device
*dev
)
218 struct drm_device
*ddev
;
221 ddev
= drm_dev_alloc(&sti_driver
, dev
);
223 return PTR_ERR(ddev
);
225 ret
= sti_init(ddev
);
227 goto err_drm_dev_put
;
229 ret
= component_bind_all(ddev
->dev
, ddev
);
233 ret
= drm_dev_register(ddev
, 0);
237 drm_mode_config_reset(ddev
);
239 drm_fbdev_generic_setup(ddev
, 32);
250 static void sti_unbind(struct device
*dev
)
252 struct drm_device
*ddev
= dev_get_drvdata(dev
);
254 drm_dev_unregister(ddev
);
259 static const struct component_master_ops sti_ops
= {
261 .unbind
= sti_unbind
,
264 static int sti_platform_probe(struct platform_device
*pdev
)
266 struct device
*dev
= &pdev
->dev
;
267 struct device_node
*node
= dev
->of_node
;
268 struct device_node
*child_np
;
269 struct component_match
*match
= NULL
;
271 dma_set_coherent_mask(dev
, DMA_BIT_MASK(32));
273 devm_of_platform_populate(dev
);
275 child_np
= of_get_next_available_child(node
, NULL
);
278 drm_of_component_match_add(dev
, &match
, compare_of
,
280 child_np
= of_get_next_available_child(node
, child_np
);
283 return component_master_add_with_match(dev
, &sti_ops
, match
);
286 static int sti_platform_remove(struct platform_device
*pdev
)
288 component_master_del(&pdev
->dev
, &sti_ops
);
293 static const struct of_device_id sti_dt_ids
[] = {
294 { .compatible
= "st,sti-display-subsystem", },
297 MODULE_DEVICE_TABLE(of
, sti_dt_ids
);
299 static struct platform_driver sti_platform_driver
= {
300 .probe
= sti_platform_probe
,
301 .remove
= sti_platform_remove
,
304 .of_match_table
= sti_dt_ids
,
308 static struct platform_driver
* const drivers
[] = {
315 &sti_compositor_driver
,
316 &sti_platform_driver
,
319 static int sti_drm_init(void)
321 return platform_register_drivers(drivers
, ARRAY_SIZE(drivers
));
323 module_init(sti_drm_init
);
325 static void sti_drm_exit(void)
327 platform_unregister_drivers(drivers
, ARRAY_SIZE(drivers
));
329 module_exit(sti_drm_exit
);
331 MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
332 MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
333 MODULE_LICENSE("GPL");