aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/msm/msm_debugfs.c1
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c15
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h10
-rw-r--r--drivers/gpu/drm/msm/msm_fbdev.c115
4 files changed, 81 insertions, 60 deletions
diff --git a/drivers/gpu/drm/msm/msm_debugfs.c b/drivers/gpu/drm/msm/msm_debugfs.c
index 7de9e39f051e..9c0e633a3a61 100644
--- a/drivers/gpu/drm/msm/msm_debugfs.c
+++ b/drivers/gpu/drm/msm/msm_debugfs.c
@@ -10,6 +10,7 @@
#include <linux/fault-inject.h>
#include <drm/drm_debugfs.h>
+#include <drm/drm_fb_helper.h>
#include <drm/drm_file.h>
#include <drm/drm_framebuffer.h>
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 2062b06f6037..29ba4bfda24b 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -58,7 +58,6 @@ static void msm_deinit_vram(struct drm_device *ddev);
static const struct drm_mode_config_funcs mode_config_funcs = {
.fb_create = msm_framebuffer_create,
- .output_poll_changed = drm_fb_helper_output_poll_changed,
.atomic_check = drm_atomic_helper_check,
.atomic_commit = drm_atomic_helper_commit,
};
@@ -236,11 +235,6 @@ static int msm_drm_uninit(struct device *dev)
msm_perf_debugfs_cleanup(priv);
msm_rd_debugfs_cleanup(priv);
-#ifdef CONFIG_DRM_FBDEV_EMULATION
- if (ddev->fb_helper)
- msm_fbdev_free(ddev);
-#endif
-
if (kms)
msm_disp_snapshot_destroy(ddev);
@@ -543,17 +537,15 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv)
}
drm_mode_config_reset(ddev);
-#ifdef CONFIG_DRM_FBDEV_EMULATION
- if (kms)
- msm_fbdev_init(ddev);
-#endif
-
ret = msm_debugfs_late_init(ddev);
if (ret)
goto err_msm_uninit;
drm_kms_helper_poll_init(ddev);
+ if (kms)
+ msm_fbdev_setup(ddev);
+
return 0;
err_msm_uninit:
@@ -1092,7 +1084,6 @@ static const struct drm_driver msm_driver = {
DRIVER_SYNCOBJ,
.open = msm_open,
.postclose = msm_postclose,
- .lastclose = drm_fb_helper_lastclose,
.dumb_create = msm_gem_dumb_create,
.dumb_map_offset = msm_gem_dumb_map_offset,
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index ddb681a104bb..33cc41f0c4e4 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -29,7 +29,6 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drm_fb_helper.h>
#include <drm/display/drm_dsc.h>
#include <drm/msm_drm.h>
#include <drm/drm_gem.h>
@@ -304,8 +303,13 @@ struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev,
struct drm_framebuffer * msm_alloc_stolen_fb(struct drm_device *dev,
int w, int h, int p, uint32_t format);
-struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev);
-void msm_fbdev_free(struct drm_device *dev);
+#ifdef CONFIG_DRM_FBDEV_EMULATION
+void msm_fbdev_setup(struct drm_device *dev);
+#else
+static inline void msm_fbdev_setup(struct drm_device *dev)
+{
+}
+#endif
struct hdmi;
#ifdef CONFIG_DRM_MSM_HDMI
diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c
index 77788c6c802d..2ebc86381e1c 100644
--- a/drivers/gpu/drm/msm/msm_fbdev.c
+++ b/drivers/gpu/drm/msm/msm_fbdev.c
@@ -4,7 +4,8 @@
* Author: Rob Clark <robdclark@gmail.com>
*/
-#include <drm/drm_crtc.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
@@ -30,6 +31,25 @@ static int msm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
return drm_gem_prime_mmap(bo, vma);
}
+static void msm_fbdev_fb_destroy(struct fb_info *info)
+{
+ struct drm_fb_helper *helper = (struct drm_fb_helper *)info->par;
+ struct drm_framebuffer *fb = helper->fb;
+ struct drm_gem_object *bo = msm_framebuffer_bo(fb, 0);
+
+ DBG();
+
+ drm_fb_helper_fini(helper);
+
+ /* this will free the backing object */
+ msm_gem_put_vaddr(bo);
+ drm_framebuffer_remove(fb);
+
+ drm_client_release(&helper->client);
+ drm_fb_helper_unprepare(helper);
+ kfree(helper);
+}
+
static const struct fb_ops msm_fb_ops = {
.owner = THIS_MODULE,
DRM_FB_HELPER_DEFAULT_OPS,
@@ -43,6 +63,7 @@ static const struct fb_ops msm_fb_ops = {
.fb_copyarea = drm_fb_helper_sys_copyarea,
.fb_imageblit = drm_fb_helper_sys_imageblit,
.fb_mmap = msm_fbdev_mmap,
+ .fb_destroy = msm_fbdev_fb_destroy,
};
static int msm_fbdev_create(struct drm_fb_helper *helper,
@@ -128,16 +149,52 @@ static const struct drm_fb_helper_funcs msm_fb_helper_funcs = {
*/
static void msm_fbdev_client_unregister(struct drm_client_dev *client)
-{ }
+{
+ struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
+
+ if (fb_helper->info) {
+ drm_fb_helper_unregister_info(fb_helper);
+ } else {
+ drm_client_release(&fb_helper->client);
+ drm_fb_helper_unprepare(fb_helper);
+ kfree(fb_helper);
+ }
+}
static int msm_fbdev_client_restore(struct drm_client_dev *client)
{
+ drm_fb_helper_lastclose(client->dev);
+
return 0;
}
static int msm_fbdev_client_hotplug(struct drm_client_dev *client)
{
+ struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
+ struct drm_device *dev = client->dev;
+ int ret;
+
+ if (dev->fb_helper)
+ return drm_fb_helper_hotplug_event(dev->fb_helper);
+
+ ret = drm_fb_helper_init(dev, fb_helper);
+ if (ret)
+ goto err_drm_err;
+
+ if (!drm_drv_uses_atomic_modeset(dev))
+ drm_helper_disable_unused_functions(dev);
+
+ ret = drm_fb_helper_initial_config(fb_helper);
+ if (ret)
+ goto err_drm_fb_helper_fini;
+
return 0;
+
+err_drm_fb_helper_fini:
+ drm_fb_helper_fini(fb_helper);
+err_drm_err:
+ drm_err(dev, "Failed to setup fbdev emulation (ret=%d)\n", ret);
+ return ret;
}
static const struct drm_client_funcs msm_fbdev_client_funcs = {
@@ -148,18 +205,20 @@ static const struct drm_client_funcs msm_fbdev_client_funcs = {
};
/* initialize fbdev helper */
-struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev)
+void msm_fbdev_setup(struct drm_device *dev)
{
struct drm_fb_helper *helper;
int ret;
if (!fbdev)
- return NULL;
+ return;
+
+ drm_WARN(dev, !dev->registered, "Device has not been registered.\n");
+ drm_WARN(dev, dev->fb_helper, "fb_helper is already set!\n");
helper = kzalloc(sizeof(*helper), GFP_KERNEL);
if (!helper)
- return NULL;
-
+ return;
drm_fb_helper_prepare(dev, helper, 32, &msm_fb_helper_funcs);
ret = drm_client_init(dev, &helper->client, "fbdev", &msm_fbdev_client_funcs);
@@ -168,49 +227,15 @@ struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev)
goto err_drm_fb_helper_unprepare;
}
- ret = drm_fb_helper_init(dev, helper);
- if (ret) {
- DRM_DEV_ERROR(dev->dev, "could not init fbdev: ret=%d\n", ret);
- goto err_drm_client_release;
- }
-
- ret = drm_fb_helper_initial_config(helper);
+ ret = msm_fbdev_client_hotplug(&helper->client);
if (ret)
- goto fini;
+ drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
- return helper;
+ drm_client_register(&helper->client);
-fini:
- drm_fb_helper_fini(helper);
-err_drm_client_release:
- drm_client_release(&helper->client);
-err_drm_fb_helper_unprepare:
- drm_fb_helper_unprepare(helper);
- kfree(helper);
- return NULL;
-}
+ return;
-void msm_fbdev_free(struct drm_device *dev)
-{
- struct drm_fb_helper *helper = dev->fb_helper;
- struct drm_framebuffer *fb = helper->fb;
-
- DBG();
-
- drm_fb_helper_unregister_info(helper);
-
- drm_fb_helper_fini(helper);
-
- /* this will free the backing object */
- if (fb) {
- struct drm_gem_object *bo = msm_framebuffer_bo(fb, 0);
- msm_gem_put_vaddr(bo);
- drm_framebuffer_remove(fb);
- }
-
- drm_client_release(&helper->client);
+err_drm_fb_helper_unprepare:
drm_fb_helper_unprepare(helper);
kfree(helper);
-
- dev->fb_helper = NULL;
}