8
8
* Seung-Woo Kim <[email protected] >
9
9
*/
10
10
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>
16
13
#include <drm/drm_fb_helper.h>
17
- #include <drm/drm_fourcc.h>
18
14
#include <drm/drm_framebuffer.h>
15
+ #include <drm/drm_gem_framebuffer_helper.h>
19
16
#include <drm/drm_prime.h>
20
- #include <drm/drm_probe_helper.h>
21
17
#include <drm/exynos_drm.h>
22
18
23
19
#include "exynos_drm_drv.h"
27
23
#define MAX_CONNECTOR 4
28
24
#define PREFERRED_BPP 32
29
25
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 );
32
30
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
+ }
37
33
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 )
40
35
{
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 );
44
40
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 );
46
46
}
47
47
48
48
static const struct fb_ops exynos_drm_fb_ops = {
@@ -54,6 +54,7 @@ static const struct fb_ops exynos_drm_fb_ops = {
54
54
.fb_fillrect = drm_fb_helper_cfb_fillrect ,
55
55
.fb_copyarea = drm_fb_helper_cfb_copyarea ,
56
56
.fb_imageblit = drm_fb_helper_cfb_imageblit ,
57
+ .fb_destroy = exynos_drm_fb_destroy ,
57
58
};
58
59
59
60
static 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,
89
90
static int exynos_drm_fbdev_create (struct drm_fb_helper * helper ,
90
91
struct drm_fb_helper_surface_size * sizes )
91
92
{
92
- struct exynos_drm_fbdev * exynos_fbdev = to_exynos_fbdev (helper );
93
93
struct exynos_drm_gem * exynos_gem ;
94
94
struct drm_device * dev = helper -> dev ;
95
95
struct drm_mode_fb_cmd2 mode_cmd = { 0 };
@@ -113,8 +113,6 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
113
113
if (IS_ERR (exynos_gem ))
114
114
return PTR_ERR (exynos_gem );
115
115
116
- exynos_fbdev -> exynos_gem = exynos_gem ;
117
-
118
116
helper -> fb =
119
117
exynos_drm_framebuffer_init (dev , & mode_cmd , & exynos_gem , 1 );
120
118
if (IS_ERR (helper -> fb )) {
@@ -127,100 +125,106 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
127
125
if (ret < 0 )
128
126
goto err_destroy_framebuffer ;
129
127
130
- return ret ;
128
+ return 0 ;
131
129
132
130
err_destroy_framebuffer :
133
131
drm_framebuffer_cleanup (helper -> fb );
132
+ helper -> fb = NULL ;
134
133
err_destroy_gem :
135
134
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
-
143
135
return ret ;
144
136
}
145
137
146
138
static const struct drm_fb_helper_funcs exynos_drm_fb_helper_funcs = {
147
139
.fb_probe = exynos_drm_fbdev_create ,
148
140
};
149
141
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 )
151
147
{
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 );
156
162
157
- if (! dev -> mode_config . num_crtc )
158
- return 0 ;
163
+ return 0 ;
164
+ }
159
165
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 ;
163
171
164
- private -> fb_helper = helper = & fbdev -> drm_fb_helper ;
172
+ if (dev -> fb_helper )
173
+ return drm_fb_helper_hotplug_event (dev -> fb_helper );
165
174
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 ;
167
178
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 );
174
181
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 ;
181
185
182
186
return 0 ;
183
187
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 );
191
192
return ret ;
192
193
}
193
194
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 )
196
203
{
197
- struct drm_framebuffer * fb ;
204
+ struct drm_fb_helper * fb_helper ;
205
+ int ret ;
198
206
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" );
205
209
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 );
207
214
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 ;
210
218
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 );
215
222
216
- if (!private || !private -> fb_helper )
217
- return ;
223
+ drm_client_register (& fb_helper -> client );
218
224
219
- fbdev = to_exynos_fbdev ( private -> fb_helper ) ;
225
+ return ;
220
226
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 );
225
230
}
226
-
0 commit comments