/** * adf_fbdev_destroy - destroy helper to wrap ADF device in fbdev API * * @fbdev: the fbdev helper */ void adf_fbdev_destroy(struct adf_fbdev *fbdev) { unregister_framebuffer(fbdev->info); if (WARN_ON(fbdev->open)) adf_fb_destroy(fbdev); framebuffer_release(fbdev->info); }
/** * adf_fbdev_release - default implementation of fbdev release op */ int adf_fbdev_release(struct fb_info *info, int user) { struct adf_fbdev *fbdev = info->par; adf_fb_destroy(fbdev); fbdev->open = false; return 0; }
/** * adf_fbdev_release - default implementation of fbdev release op */ int adf_fbdev_release(struct fb_info *info, int user) { struct adf_fbdev *fbdev = info->par; mutex_lock(&fbdev->refcount_lock); BUG_ON(!fbdev->refcount); fbdev->refcount--; if (!fbdev->refcount) adf_fb_destroy(fbdev); mutex_unlock(&fbdev->refcount_lock); return 0; }
/** * adf_fbdev_open - default implementation of fbdev open op */ int adf_fbdev_open(struct fb_info *info, int user) { struct adf_fbdev *fbdev = info->par; int ret; mutex_lock(&fbdev->refcount_lock); if (unlikely(fbdev->refcount == UINT_MAX)) { ret = -EMFILE; goto done; } if (!fbdev->refcount) { struct drm_mode_modeinfo mode; struct fb_videomode fbmode; struct adf_device *dev = adf_interface_parent(fbdev->intf); ret = adf_device_attach(dev, fbdev->eng, fbdev->intf); if (ret < 0 && ret != -EALREADY) goto done; ret = adf_fb_alloc(fbdev); if (ret < 0) goto done; adf_interface_current_mode(fbdev->intf, &mode); adf_modeinfo_to_fb_videomode(&mode, &fbmode); fb_videomode_to_var(&fbdev->info->var, &fbmode); adf_fbdev_set_format(fbdev, fbdev->default_format); adf_fbdev_fill_modelist(fbdev); } if (!fbdev_opened_once) { fbdev_opened_once = true; } else { ret = adf_fbdev_post(fbdev); if (ret < 0) { if (!fbdev->refcount) adf_fb_destroy(fbdev); goto done; } } fbdev->refcount++; done: mutex_unlock(&fbdev->refcount_lock); return ret; }
/** * adf_fbdev_open - default implementation of fbdev open op */ int adf_fbdev_open(struct fb_info *info, int user) { struct adf_fbdev *fbdev = info->par; int ret; if (!fbdev->open) { struct drm_mode_modeinfo mode; struct fb_videomode fbmode; struct adf_device *dev = adf_interface_parent(fbdev->intf); ret = adf_device_attach(dev, fbdev->eng, fbdev->intf); if (ret < 0 && ret != -EALREADY) return ret; ret = adf_fb_alloc(fbdev); if (ret < 0) return ret; adf_interface_current_mode(fbdev->intf, &mode); adf_modeinfo_to_fb_videomode(&mode, &fbmode); fb_videomode_to_var(&fbdev->info->var, &fbmode); adf_fbdev_set_format(fbdev, fbdev->default_format); adf_fbdev_fill_modelist(fbdev); } ret = adf_fbdev_post(fbdev); if (ret < 0) { if (!fbdev->open) adf_fb_destroy(fbdev); return ret; } fbdev->open = true; return 0; }