Skip to content

Commit 289af45

Browse files
committed
Merge tag 'exynos-drm-next-for-v6.4-2' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next
A patch series for implementing fbdev emulation as in-kernel client. - This patch series refactors fbdev callbacks to DRM client functions and simplifies fbdev emulation initialization including some code cleanups. The changes make fbdev emulation behave like a regular DRM client. Signed-off-by: Dave Airlie <[email protected]> From: Inki Dae <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
2 parents 02a8ae7 + 49953b7 commit 289af45

File tree

5 files changed

+94
-117
lines changed

5 files changed

+94
-117
lines changed

drivers/gpu/drm/exynos/exynos_drm_drv.c

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
#include <drm/drm_atomic.h>
1717
#include <drm/drm_atomic_helper.h>
1818
#include <drm/drm_drv.h>
19-
#include <drm/drm_fb_helper.h>
2019
#include <drm/drm_file.h>
2120
#include <drm/drm_fourcc.h>
2221
#include <drm/drm_ioctl.h>
@@ -108,7 +107,6 @@ static const struct drm_driver exynos_drm_driver = {
108107
.driver_features = DRIVER_MODESET | DRIVER_GEM
109108
| DRIVER_ATOMIC | DRIVER_RENDER,
110109
.open = exynos_drm_open,
111-
.lastclose = drm_fb_helper_lastclose,
112110
.postclose = exynos_drm_postclose,
113111
.dumb_create = exynos_drm_gem_dumb_create,
114112
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
@@ -288,19 +286,15 @@ static int exynos_drm_bind(struct device *dev)
288286
/* init kms poll for handling hpd */
289287
drm_kms_helper_poll_init(drm);
290288

291-
ret = exynos_drm_fbdev_init(drm);
292-
if (ret)
293-
goto err_cleanup_poll;
294-
295289
/* register the DRM device */
296290
ret = drm_dev_register(drm, 0);
297291
if (ret < 0)
298-
goto err_cleanup_fbdev;
292+
goto err_cleanup_poll;
293+
294+
exynos_drm_fbdev_setup(drm);
299295

300296
return 0;
301297

302-
err_cleanup_fbdev:
303-
exynos_drm_fbdev_fini(drm);
304298
err_cleanup_poll:
305299
drm_kms_helper_poll_fini(drm);
306300
err_unbind_all:
@@ -321,7 +315,6 @@ static void exynos_drm_unbind(struct device *dev)
321315

322316
drm_dev_unregister(drm);
323317

324-
exynos_drm_fbdev_fini(drm);
325318
drm_kms_helper_poll_fini(drm);
326319

327320
component_unbind_all(drm->dev, drm);

drivers/gpu/drm/exynos/exynos_drm_drv.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,6 @@ struct drm_exynos_file_private {
197197
* @wait: wait an atomic commit to finish
198198
*/
199199
struct exynos_drm_private {
200-
struct drm_fb_helper *fb_helper;
201-
202200
struct device *g2d_dev;
203201
struct device *dma_dev;
204202
void *mapping;

drivers/gpu/drm/exynos/exynos_drm_fb.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
#include <drm/drm_atomic.h>
1212
#include <drm/drm_atomic_helper.h>
1313
#include <drm/drm_crtc.h>
14-
#include <drm/drm_fb_helper.h>
1514
#include <drm/drm_framebuffer.h>
1615
#include <drm/drm_fourcc.h>
1716
#include <drm/drm_gem_framebuffer_helper.h>
@@ -157,7 +156,6 @@ static struct drm_mode_config_helper_funcs exynos_drm_mode_config_helpers = {
157156

158157
static const struct drm_mode_config_funcs exynos_drm_mode_config_funcs = {
159158
.fb_create = exynos_user_fb_create,
160-
.output_poll_changed = drm_fb_helper_output_poll_changed,
161159
.atomic_check = drm_atomic_helper_check,
162160
.atomic_commit = drm_atomic_helper_commit,
163161
};

drivers/gpu/drm/exynos/exynos_drm_fbdev.c

Lines changed: 89 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,12 @@
88
* Seung-Woo Kim <[email protected]>
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"
@@ -27,22 +23,26 @@
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

4848
static 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

5960
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,
8990
static 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

132130
err_destroy_framebuffer:
133131
drm_framebuffer_cleanup(helper->fb);
132+
helper->fb = NULL;
134133
err_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

146138
static 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-

drivers/gpu/drm/exynos/exynos_drm_fbdev.h

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,11 @@
1212
#define _EXYNOS_DRM_FBDEV_H_
1313

1414
#ifdef CONFIG_DRM_FBDEV_EMULATION
15-
16-
int exynos_drm_fbdev_init(struct drm_device *dev);
17-
void exynos_drm_fbdev_fini(struct drm_device *dev);
18-
15+
void exynos_drm_fbdev_setup(struct drm_device *dev);
1916
#else
20-
21-
static inline int exynos_drm_fbdev_init(struct drm_device *dev)
22-
{
23-
return 0;
24-
}
25-
26-
static inline void exynos_drm_fbdev_fini(struct drm_device *dev)
17+
static inline void exynos_drm_fbdev_setup(struct drm_device *dev)
2718
{
2819
}
29-
30-
static inline void exynos_drm_fbdev_restore_mode(struct drm_device *dev)
31-
{
32-
}
33-
34-
#define exynos_drm_output_poll_changed (NULL)
35-
3620
#endif
3721

3822
#endif

0 commit comments

Comments
 (0)