summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/gma500/fbdev.c153
-rw-r--r--drivers/gpu/drm/gma500/framebuffer.c3
-rw-r--r--drivers/gpu/drm/gma500/psb_drv.c5
-rw-r--r--drivers/gpu/drm/gma500/psb_drv.h12
4 files changed, 106 insertions, 67 deletions
diff --git a/drivers/gpu/drm/gma500/fbdev.c b/drivers/gpu/drm/gma500/fbdev.c
index 74e843f8e64d..0433392c7fbf 100644
--- a/drivers/gpu/drm/gma500/fbdev.c
+++ b/drivers/gpu/drm/gma500/fbdev.c
@@ -8,6 +8,7 @@
#include <linux/pfn_t.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_drv.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_framebuffer.h>
@@ -121,6 +122,27 @@ static int psb_fbdev_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
return 0;
}
+static void psb_fbdev_fb_destroy(struct fb_info *info)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+ struct drm_framebuffer *fb = fb_helper->fb;
+ struct drm_gem_object *obj = fb->obj[0];
+
+ drm_fb_helper_fini(fb_helper);
+
+ drm_framebuffer_unregister_private(fb);
+ fb->obj[0] = NULL;
+ drm_framebuffer_cleanup(fb);
+ kfree(fb);
+
+ drm_gem_object_put(obj);
+
+ drm_client_release(&fb_helper->client);
+
+ drm_fb_helper_unprepare(fb_helper);
+ kfree(fb_helper);
+}
+
static const struct fb_ops psb_fbdev_fb_ops = {
.owner = THIS_MODULE,
DRM_FB_HELPER_DEFAULT_OPS,
@@ -131,6 +153,7 @@ static const struct fb_ops psb_fbdev_fb_ops = {
.fb_copyarea = drm_fb_helper_cfb_copyarea,
.fb_imageblit = drm_fb_helper_cfb_imageblit,
.fb_mmap = psb_fbdev_fb_mmap,
+ .fb_destroy = psb_fbdev_fb_destroy,
};
/*
@@ -190,14 +213,6 @@ static int psb_fbdev_fb_probe(struct drm_fb_helper *fb_helper,
return PTR_ERR(backing);
obj = &backing->base;
- memset(dev_priv->vram_addr + backing->offset, 0, size);
-
- info = drm_fb_helper_alloc_info(fb_helper);
- if (IS_ERR(info)) {
- ret = PTR_ERR(info);
- goto err_drm_gem_object_put;
- }
-
fb = psb_framebuffer_create(dev, &mode_cmd, obj);
if (IS_ERR(fb)) {
ret = PTR_ERR(fb);
@@ -206,28 +221,40 @@ static int psb_fbdev_fb_probe(struct drm_fb_helper *fb_helper,
fb_helper->fb = fb;
- info->fbops = &psb_fbdev_fb_ops;
-
- info->fix.smem_start = dev_priv->fb_base;
- info->fix.smem_len = size;
- info->fix.ywrapstep = 0;
- info->fix.ypanstep = 0;
+ info = drm_fb_helper_alloc_info(fb_helper);
+ if (IS_ERR(info)) {
+ ret = PTR_ERR(info);
+ goto err_drm_framebuffer_unregister_private;
+ }
+ info->fbops = &psb_fbdev_fb_ops;
+ info->flags = FBINFO_DEFAULT;
/* Accessed stolen memory directly */
info->screen_base = dev_priv->vram_addr + backing->offset;
info->screen_size = size;
drm_fb_helper_fill_info(info, fb_helper, sizes);
+ info->fix.smem_start = dev_priv->fb_base;
+ info->fix.smem_len = size;
+ info->fix.ywrapstep = 0;
+ info->fix.ypanstep = 0;
info->fix.mmio_start = pci_resource_start(pdev, 0);
info->fix.mmio_len = pci_resource_len(pdev, 0);
+ memset(info->screen_base, 0, info->screen_size);
+
/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
dev_dbg(dev->dev, "allocated %dx%d fb\n", fb->width, fb->height);
return 0;
+err_drm_framebuffer_unregister_private:
+ drm_framebuffer_unregister_private(fb);
+ fb->obj[0] = NULL;
+ drm_framebuffer_cleanup(fb);
+ kfree(fb);
err_drm_gem_object_put:
drm_gem_object_put(obj);
return ret;
@@ -237,68 +264,92 @@ static const struct drm_fb_helper_funcs psb_fbdev_fb_helper_funcs = {
.fb_probe = psb_fbdev_fb_probe,
};
-static int psb_fbdev_destroy(struct drm_device *dev,
- struct drm_fb_helper *fb_helper)
-{
- struct drm_framebuffer *fb = fb_helper->fb;
-
- drm_fb_helper_unregister_info(fb_helper);
+/*
+ * struct drm_client_funcs and setup code
+ */
- drm_fb_helper_fini(fb_helper);
- drm_framebuffer_unregister_private(fb);
- drm_framebuffer_cleanup(fb);
+static void psb_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_fb_helper_unprepare(fb_helper);
+ drm_client_release(&fb_helper->client);
+ kfree(fb_helper);
+ }
+}
- if (fb->obj[0])
- drm_gem_object_put(fb->obj[0]);
- kfree(fb);
+static int psb_fbdev_client_restore(struct drm_client_dev *client)
+{
+ drm_fb_helper_lastclose(client->dev);
return 0;
}
-int psb_fbdev_init(struct drm_device *dev)
+static int psb_fbdev_client_hotplug(struct drm_client_dev *client)
{
- struct drm_fb_helper *fb_helper;
- struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
+ struct drm_device *dev = client->dev;
int ret;
- fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);
- if (!fb_helper)
- return -ENOMEM;
-
- dev_priv->fb_helper = fb_helper;
-
- drm_fb_helper_prepare(dev, fb_helper, 32, &psb_fbdev_fb_helper_funcs);
+ if (dev->fb_helper)
+ return drm_fb_helper_hotplug_event(dev->fb_helper);
ret = drm_fb_helper_init(dev, fb_helper);
if (ret)
- goto free;
+ goto err_drm_err;
- /* disable all the possible outputs/crtcs before entering KMS mode */
- drm_helper_disable_unused_functions(dev);
+ if (!drm_drv_uses_atomic_modeset(dev))
+ drm_helper_disable_unused_functions(dev);
ret = drm_fb_helper_initial_config(fb_helper);
if (ret)
- goto fini;
+ goto err_drm_fb_helper_fini;
return 0;
-fini:
+err_drm_fb_helper_fini:
drm_fb_helper_fini(fb_helper);
-free:
- drm_fb_helper_unprepare(fb_helper);
- kfree(fb_helper);
+err_drm_err:
+ drm_err(dev, "Failed to setup gma500 fbdev emulation (ret=%d)\n", ret);
return ret;
}
-void psb_fbdev_fini(struct drm_device *dev)
+static const struct drm_client_funcs psb_fbdev_client_funcs = {
+ .owner = THIS_MODULE,
+ .unregister = psb_fbdev_client_unregister,
+ .restore = psb_fbdev_client_restore,
+ .hotplug = psb_fbdev_client_hotplug,
+};
+
+void psb_fbdev_setup(struct drm_psb_private *dev_priv)
{
- struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct drm_device *dev = &dev_priv->dev;
+ struct drm_fb_helper *fb_helper;
+ int ret;
- if (!dev_priv->fb_helper)
+ fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);
+ if (!fb_helper)
return;
+ drm_fb_helper_prepare(dev, fb_helper, 32, &psb_fbdev_fb_helper_funcs);
+
+ ret = drm_client_init(dev, &fb_helper->client, "fbdev-gma500", &psb_fbdev_client_funcs);
+ if (ret) {
+ drm_err(dev, "Failed to register client: %d\n", ret);
+ goto err_drm_fb_helper_unprepare;
+ }
+
+ ret = psb_fbdev_client_hotplug(&fb_helper->client);
+ if (ret)
+ drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
+
+ drm_client_register(&fb_helper->client);
+
+ return;
- psb_fbdev_destroy(dev, dev_priv->fb_helper);
- drm_fb_helper_unprepare(dev_priv->fb_helper);
- kfree(dev_priv->fb_helper);
- dev_priv->fb_helper = NULL;
+err_drm_fb_helper_unprepare:
+ drm_fb_helper_unprepare(fb_helper);
+ kfree(fb_helper);
}
diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c
index 506b881a7b24..f5c3bae95eb5 100644
--- a/drivers/gpu/drm/gma500/framebuffer.c
+++ b/drivers/gpu/drm/gma500/framebuffer.c
@@ -5,7 +5,6 @@
*
**************************************************************************/
-#include <drm/drm_fb_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_modeset_helper.h>
@@ -120,7 +119,6 @@ static struct drm_framebuffer *psb_user_framebuffer_create
static const struct drm_mode_config_funcs psb_mode_funcs = {
.fb_create = psb_user_framebuffer_create,
- .output_poll_changed = drm_fb_helper_output_poll_changed,
};
static void psb_setup_outputs(struct drm_device *dev)
@@ -223,6 +221,5 @@ void psb_modeset_cleanup(struct drm_device *dev)
struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
if (dev_priv->modeset) {
drm_kms_helper_poll_fini(dev);
- psb_fbdev_fini(dev);
}
}
diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
index cd9c73f5a64a..2ce96b1b9c74 100644
--- a/drivers/gpu/drm/gma500/psb_drv.c
+++ b/drivers/gpu/drm/gma500/psb_drv.c
@@ -21,7 +21,6 @@
#include <drm/drm.h>
#include <drm/drm_aperture.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_file.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_pciids.h>
@@ -387,7 +386,6 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags)
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
psb_modeset_init(dev);
- psb_fbdev_init(dev);
drm_kms_helper_poll_init(dev);
/* Only add backlight support if we have LVDS or MIPI output */
@@ -452,6 +450,8 @@ static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret)
return ret;
+ psb_fbdev_setup(dev_priv);
+
return 0;
}
@@ -477,7 +477,6 @@ static const struct file_operations psb_gem_fops = {
static const struct drm_driver driver = {
.driver_features = DRIVER_MODESET | DRIVER_GEM,
- .lastclose = drm_fb_helper_lastclose,
.num_ioctls = ARRAY_SIZE(psb_ioctls),
diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h
index 5d2ccb5280a4..931f62c1d942 100644
--- a/drivers/gpu/drm/gma500/psb_drv.h
+++ b/drivers/gpu/drm/gma500/psb_drv.h
@@ -193,8 +193,6 @@
#define KSEL_BYPASS_25 6
#define KSEL_BYPASS_83_100 7
-struct drm_fb_helper;
-
struct opregion_header;
struct opregion_acpi;
struct opregion_swsci;
@@ -522,7 +520,6 @@ struct drm_psb_private {
uint32_t blc_adj1;
uint32_t blc_adj2;
- struct drm_fb_helper *fb_helper;
resource_size_t fb_base;
bool dsr_enable;
@@ -618,14 +615,9 @@ struct drm_framebuffer *psb_framebuffer_create(struct drm_device *dev,
/* fbdev */
#if defined(CONFIG_DRM_FBDEV_EMULATION)
-extern int psb_fbdev_init(struct drm_device *dev);
-extern void psb_fbdev_fini(struct drm_device *dev);
+void psb_fbdev_setup(struct drm_psb_private *dev_priv);
#else
-static inline int psb_fbdev_init(struct drm_device *dev)
-{
- return 0;
-}
-static inline void psb_fbdev_fini(struct drm_device *dev)
+static inline void psb_fbdev_setup(struct drm_psb_private *dev_priv)
{ }
#endif