diff options
-rw-r--r-- | drivers/gpu/drm/gma500/fbdev.c | 153 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/framebuffer.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/psb_drv.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/psb_drv.h | 12 |
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 |