88 * Seung-Woo Kim <sw0312.kim@samsung.com>
99 */
1010
11- #include <linux/console.h>
12- #include <linux/dma-mapping.h>
13- #include <linux/vmalloc.h>
14-
15- #include <drm/drm_crtc.h>
11+ #include <drm/drm_crtc_helper.h>
12+ #include <drm/drm_drv.h>
1613#include <drm/drm_fb_helper.h>
17- #include <drm/drm_fourcc.h>
1814#include <drm/drm_framebuffer.h>
15+ #include <drm/drm_gem_framebuffer_helper.h>
1916#include <drm/drm_prime.h>
20- #include <drm/drm_probe_helper.h>
2117#include <drm/exynos_drm.h>
2218
2319#include "exynos_drm_drv.h"
2723#define MAX_CONNECTOR 4
2824#define PREFERRED_BPP 32
2925
30- #define to_exynos_fbdev (x ) container_of(x, struct exynos_drm_fbdev,\
31- drm_fb_helper)
26+ static int exynos_drm_fb_mmap (struct fb_info * info , struct vm_area_struct * vma )
27+ {
28+ struct drm_fb_helper * helper = info -> par ;
29+ struct drm_gem_object * obj = drm_gem_fb_get_obj (helper -> fb , 0 );
3230
33- struct exynos_drm_fbdev {
34- struct drm_fb_helper drm_fb_helper ;
35- struct exynos_drm_gem * exynos_gem ;
36- };
31+ return drm_gem_prime_mmap (obj , vma );
32+ }
3733
38- static int exynos_drm_fb_mmap (struct fb_info * info ,
39- struct vm_area_struct * vma )
34+ static void exynos_drm_fb_destroy (struct fb_info * info )
4035{
41- struct drm_fb_helper * helper = info -> par ;
42- struct exynos_drm_fbdev * exynos_fbd = to_exynos_fbdev (helper );
43- struct exynos_drm_gem * exynos_gem = exynos_fbd -> exynos_gem ;
36+ struct drm_fb_helper * fb_helper = info -> par ;
37+ struct drm_framebuffer * fb = fb_helper -> fb ;
38+
39+ drm_fb_helper_fini (fb_helper );
4440
45- return drm_gem_prime_mmap (& exynos_gem -> base , vma );
41+ drm_framebuffer_remove (fb );
42+
43+ drm_client_release (& fb_helper -> client );
44+ drm_fb_helper_unprepare (fb_helper );
45+ kfree (fb_helper );
4646}
4747
4848static const struct fb_ops exynos_drm_fb_ops = {
@@ -54,6 +54,7 @@ static const struct fb_ops exynos_drm_fb_ops = {
5454 .fb_fillrect = drm_fb_helper_cfb_fillrect ,
5555 .fb_copyarea = drm_fb_helper_cfb_copyarea ,
5656 .fb_imageblit = drm_fb_helper_cfb_imageblit ,
57+ .fb_destroy = exynos_drm_fb_destroy ,
5758};
5859
5960static int exynos_drm_fbdev_update (struct drm_fb_helper * helper ,
@@ -89,7 +90,6 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
8990static int exynos_drm_fbdev_create (struct drm_fb_helper * helper ,
9091 struct drm_fb_helper_surface_size * sizes )
9192{
92- struct exynos_drm_fbdev * exynos_fbdev = to_exynos_fbdev (helper );
9393 struct exynos_drm_gem * exynos_gem ;
9494 struct drm_device * dev = helper -> dev ;
9595 struct drm_mode_fb_cmd2 mode_cmd = { 0 };
@@ -113,8 +113,6 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
113113 if (IS_ERR (exynos_gem ))
114114 return PTR_ERR (exynos_gem );
115115
116- exynos_fbdev -> exynos_gem = exynos_gem ;
117-
118116 helper -> fb =
119117 exynos_drm_framebuffer_init (dev , & mode_cmd , & exynos_gem , 1 );
120118 if (IS_ERR (helper -> fb )) {
@@ -127,100 +125,106 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
127125 if (ret < 0 )
128126 goto err_destroy_framebuffer ;
129127
130- return ret ;
128+ return 0 ;
131129
132130err_destroy_framebuffer :
133131 drm_framebuffer_cleanup (helper -> fb );
132+ helper -> fb = NULL ;
134133err_destroy_gem :
135134 exynos_drm_gem_destroy (exynos_gem );
136-
137- /*
138- * if failed, all resources allocated above would be released by
139- * drm_mode_config_cleanup() when drm_load() had been called prior
140- * to any specific driver such as fimd or hdmi driver.
141- */
142-
143135 return ret ;
144136}
145137
146138static const struct drm_fb_helper_funcs exynos_drm_fb_helper_funcs = {
147139 .fb_probe = exynos_drm_fbdev_create ,
148140};
149141
150- int exynos_drm_fbdev_init (struct drm_device * dev )
142+ /*
143+ * struct drm_client
144+ */
145+
146+ static void exynos_drm_fbdev_client_unregister (struct drm_client_dev * client )
151147{
152- struct exynos_drm_fbdev * fbdev ;
153- struct exynos_drm_private * private = dev -> dev_private ;
154- struct drm_fb_helper * helper ;
155- int ret ;
148+ struct drm_fb_helper * fb_helper = drm_fb_helper_from_client (client );
149+
150+ if (fb_helper -> info ) {
151+ drm_fb_helper_unregister_info (fb_helper );
152+ } else {
153+ drm_client_release (& fb_helper -> client );
154+ drm_fb_helper_unprepare (fb_helper );
155+ kfree (fb_helper );
156+ }
157+ }
158+
159+ static int exynos_drm_fbdev_client_restore (struct drm_client_dev * client )
160+ {
161+ drm_fb_helper_lastclose (client -> dev );
156162
157- if (! dev -> mode_config . num_crtc )
158- return 0 ;
163+ return 0 ;
164+ }
159165
160- fbdev = kzalloc (sizeof (* fbdev ), GFP_KERNEL );
161- if (!fbdev )
162- return - ENOMEM ;
166+ static int exynos_drm_fbdev_client_hotplug (struct drm_client_dev * client )
167+ {
168+ struct drm_fb_helper * fb_helper = drm_fb_helper_from_client (client );
169+ struct drm_device * dev = client -> dev ;
170+ int ret ;
163171
164- private -> fb_helper = helper = & fbdev -> drm_fb_helper ;
172+ if (dev -> fb_helper )
173+ return drm_fb_helper_hotplug_event (dev -> fb_helper );
165174
166- drm_fb_helper_prepare (dev , helper , PREFERRED_BPP , & exynos_drm_fb_helper_funcs );
175+ ret = drm_fb_helper_init (dev , fb_helper );
176+ if (ret )
177+ goto err_drm_err ;
167178
168- ret = drm_fb_helper_init (dev , helper );
169- if (ret < 0 ) {
170- DRM_DEV_ERROR (dev -> dev ,
171- "failed to initialize drm fb helper.\n" );
172- goto err_init ;
173- }
179+ if (!drm_drv_uses_atomic_modeset (dev ))
180+ drm_helper_disable_unused_functions (dev );
174181
175- ret = drm_fb_helper_initial_config (helper );
176- if (ret < 0 ) {
177- DRM_DEV_ERROR (dev -> dev ,
178- "failed to set up hw configuration.\n" );
179- goto err_setup ;
180- }
182+ ret = drm_fb_helper_initial_config (fb_helper );
183+ if (ret )
184+ goto err_drm_fb_helper_fini ;
181185
182186 return 0 ;
183187
184- err_setup :
185- drm_fb_helper_fini (helper );
186- err_init :
187- drm_fb_helper_unprepare (helper );
188- private -> fb_helper = NULL ;
189- kfree (fbdev );
190-
188+ err_drm_fb_helper_fini :
189+ drm_fb_helper_fini (fb_helper );
190+ err_drm_err :
191+ drm_err (dev , "Failed to setup fbdev emulation (ret=%d)\n" , ret );
191192 return ret ;
192193}
193194
194- static void exynos_drm_fbdev_destroy (struct drm_device * dev ,
195- struct drm_fb_helper * fb_helper )
195+ static const struct drm_client_funcs exynos_drm_fbdev_client_funcs = {
196+ .owner = THIS_MODULE ,
197+ .unregister = exynos_drm_fbdev_client_unregister ,
198+ .restore = exynos_drm_fbdev_client_restore ,
199+ .hotplug = exynos_drm_fbdev_client_hotplug ,
200+ };
201+
202+ void exynos_drm_fbdev_setup (struct drm_device * dev )
196203{
197- struct drm_framebuffer * fb ;
204+ struct drm_fb_helper * fb_helper ;
205+ int ret ;
198206
199- /* release drm framebuffer and real buffer */
200- if (fb_helper -> fb && fb_helper -> fb -> funcs ) {
201- fb = fb_helper -> fb ;
202- if (fb )
203- drm_framebuffer_remove (fb );
204- }
207+ drm_WARN (dev , !dev -> registered , "Device has not been registered.\n" );
208+ drm_WARN (dev , dev -> fb_helper , "fb_helper is already set!\n" );
205209
206- drm_fb_helper_unregister_info (fb_helper );
210+ fb_helper = kzalloc (sizeof (* fb_helper ), GFP_KERNEL );
211+ if (!fb_helper )
212+ return ;
213+ drm_fb_helper_prepare (dev , fb_helper , PREFERRED_BPP , & exynos_drm_fb_helper_funcs );
207214
208- drm_fb_helper_fini (fb_helper );
209- }
215+ ret = drm_client_init (dev , & fb_helper -> client , "fbdev" , & exynos_drm_fbdev_client_funcs );
216+ if (ret )
217+ goto err_drm_client_init ;
210218
211- void exynos_drm_fbdev_fini (struct drm_device * dev )
212- {
213- struct exynos_drm_private * private = dev -> dev_private ;
214- struct exynos_drm_fbdev * fbdev ;
219+ ret = exynos_drm_fbdev_client_hotplug (& fb_helper -> client );
220+ if (ret )
221+ drm_dbg_kms (dev , "client hotplug ret=%d\n" , ret );
215222
216- if (!private || !private -> fb_helper )
217- return ;
223+ drm_client_register (& fb_helper -> client );
218224
219- fbdev = to_exynos_fbdev ( private -> fb_helper ) ;
225+ return ;
220226
221- exynos_drm_fbdev_destroy (dev , private -> fb_helper );
222- drm_fb_helper_unprepare (private -> fb_helper );
223- kfree (fbdev );
224- private -> fb_helper = NULL ;
227+ err_drm_client_init :
228+ drm_fb_helper_unprepare (fb_helper );
229+ kfree (fb_helper );
225230}
226-
0 commit comments