2 * Copyright (C) STMicroelectronics SA 2017
4 * Authors: Philippe Cornu <philippe.cornu@st.com>
5 * Yannick Fertre <yannick.fertre@st.com>
6 * Fabien Dessenne <fabien.dessenne@st.com>
7 * Mickael Reulier <mickael.reulier@st.com>
9 * License terms: GNU General Public License (GPL), version 2
12 #include <linux/component.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_fb_cma_helper.h>
19 #include <drm/drm_gem_cma_helper.h>
23 #define DRIVER_NAME "stm"
24 #define DRIVER_DESC "STMicroelectronics SoC DRM"
25 #define DRIVER_DATE "20170330"
26 #define DRIVER_MAJOR 1
27 #define DRIVER_MINOR 0
28 #define DRIVER_PATCH_LEVEL 0
30 #define STM_MAX_FB_WIDTH 2048
31 #define STM_MAX_FB_HEIGHT 2048 /* same as width to handle orientation */
33 static void drv_output_poll_changed(struct drm_device
*ddev
)
35 struct ltdc_device
*ldev
= ddev
->dev_private
;
37 drm_fbdev_cma_hotplug_event(ldev
->fbdev
);
40 static const struct drm_mode_config_funcs drv_mode_config_funcs
= {
41 .fb_create
= drm_fb_cma_create
,
42 .output_poll_changed
= drv_output_poll_changed
,
43 .atomic_check
= drm_atomic_helper_check
,
44 .atomic_commit
= drm_atomic_helper_commit
,
47 static void drv_lastclose(struct drm_device
*ddev
)
49 struct ltdc_device
*ldev
= ddev
->dev_private
;
51 DRM_DEBUG("%s\n", __func__
);
53 drm_fbdev_cma_restore_mode(ldev
->fbdev
);
56 DEFINE_DRM_GEM_CMA_FOPS(drv_driver_fops
);
58 static struct drm_driver drv_driver
= {
59 .driver_features
= DRIVER_MODESET
| DRIVER_GEM
| DRIVER_PRIME
|
61 .lastclose
= drv_lastclose
,
65 .major
= DRIVER_MAJOR
,
66 .minor
= DRIVER_MINOR
,
67 .patchlevel
= DRIVER_PATCH_LEVEL
,
68 .fops
= &drv_driver_fops
,
69 .dumb_create
= drm_gem_cma_dumb_create
,
70 .dumb_map_offset
= drm_gem_cma_dumb_map_offset
,
71 .dumb_destroy
= drm_gem_dumb_destroy
,
72 .prime_handle_to_fd
= drm_gem_prime_handle_to_fd
,
73 .prime_fd_to_handle
= drm_gem_prime_fd_to_handle
,
74 .gem_free_object_unlocked
= drm_gem_cma_free_object
,
75 .gem_vm_ops
= &drm_gem_cma_vm_ops
,
76 .gem_prime_export
= drm_gem_prime_export
,
77 .gem_prime_import
= drm_gem_prime_import
,
78 .gem_prime_get_sg_table
= drm_gem_cma_prime_get_sg_table
,
79 .gem_prime_import_sg_table
= drm_gem_cma_prime_import_sg_table
,
80 .gem_prime_vmap
= drm_gem_cma_prime_vmap
,
81 .gem_prime_vunmap
= drm_gem_cma_prime_vunmap
,
82 .gem_prime_mmap
= drm_gem_cma_prime_mmap
,
83 .enable_vblank
= ltdc_crtc_enable_vblank
,
84 .disable_vblank
= ltdc_crtc_disable_vblank
,
87 static int drv_load(struct drm_device
*ddev
)
89 struct platform_device
*pdev
= to_platform_device(ddev
->dev
);
90 struct drm_fbdev_cma
*fbdev
;
91 struct ltdc_device
*ldev
;
94 DRM_DEBUG("%s\n", __func__
);
96 ldev
= devm_kzalloc(ddev
->dev
, sizeof(*ldev
), GFP_KERNEL
);
100 ddev
->dev_private
= (void *)ldev
;
102 drm_mode_config_init(ddev
);
105 * set max width and height as default value.
106 * this value would be used to check framebuffer size limitation
107 * at drm_mode_addfb().
109 ddev
->mode_config
.min_width
= 0;
110 ddev
->mode_config
.min_height
= 0;
111 ddev
->mode_config
.max_width
= STM_MAX_FB_WIDTH
;
112 ddev
->mode_config
.max_height
= STM_MAX_FB_HEIGHT
;
113 ddev
->mode_config
.funcs
= &drv_mode_config_funcs
;
115 ret
= ltdc_load(ddev
);
119 drm_mode_config_reset(ddev
);
120 drm_kms_helper_poll_init(ddev
);
122 if (ddev
->mode_config
.num_connector
) {
123 ldev
= ddev
->dev_private
;
124 fbdev
= drm_fbdev_cma_init(ddev
, 16,
125 ddev
->mode_config
.num_connector
);
127 DRM_DEBUG("Warning: fails to create fbdev\n");
133 platform_set_drvdata(pdev
, ddev
);
137 drm_mode_config_cleanup(ddev
);
141 static void drv_unload(struct drm_device
*ddev
)
143 struct ltdc_device
*ldev
= ddev
->dev_private
;
145 DRM_DEBUG("%s\n", __func__
);
148 drm_fbdev_cma_fini(ldev
->fbdev
);
151 drm_kms_helper_poll_fini(ddev
);
153 drm_mode_config_cleanup(ddev
);
156 static int stm_drm_platform_probe(struct platform_device
*pdev
)
158 struct device
*dev
= &pdev
->dev
;
159 struct drm_device
*ddev
;
162 DRM_DEBUG("%s\n", __func__
);
164 dma_set_coherent_mask(dev
, DMA_BIT_MASK(32));
166 ddev
= drm_dev_alloc(&drv_driver
, dev
);
168 return PTR_ERR(ddev
);
170 ret
= drv_load(ddev
);
174 ret
= drm_dev_register(ddev
, 0);
186 static int stm_drm_platform_remove(struct platform_device
*pdev
)
188 struct drm_device
*ddev
= platform_get_drvdata(pdev
);
190 DRM_DEBUG("%s\n", __func__
);
192 drm_dev_unregister(ddev
);
199 static const struct of_device_id drv_dt_ids
[] = {
200 { .compatible
= "st,stm32-ltdc"},
203 MODULE_DEVICE_TABLE(of
, drv_dt_ids
);
205 static struct platform_driver stm_drm_platform_driver
= {
206 .probe
= stm_drm_platform_probe
,
207 .remove
= stm_drm_platform_remove
,
210 .of_match_table
= drv_dt_ids
,
214 module_platform_driver(stm_drm_platform_driver
);
216 MODULE_AUTHOR("Philippe Cornu <philippe.cornu@st.com>");
217 MODULE_AUTHOR("Yannick Fertre <yannick.fertre@st.com>");
218 MODULE_AUTHOR("Fabien Dessenne <fabien.dessenne@st.com>");
219 MODULE_AUTHOR("Mickael Reulier <mickael.reulier@st.com>");
220 MODULE_DESCRIPTION("STMicroelectronics ST DRM LTDC driver");
221 MODULE_LICENSE("GPL v2");