static void adf_fbdev_fill_modelist(struct adf_fbdev *fbdev) { struct drm_mode_modeinfo *modelist; struct fb_videomode fbmode; size_t n_modes, i; int ret = 0; n_modes = adf_interface_modelist(fbdev->intf, NULL, 0); modelist = kzalloc(sizeof(modelist[0]) * n_modes, GFP_KERNEL); if (!modelist) { dev_warn(fbdev->info->dev, "allocating new modelist failed; keeping old modelist\n"); return; } adf_interface_modelist(fbdev->intf, modelist, n_modes); fb_destroy_modelist(&fbdev->info->modelist); for (i = 0; i < n_modes; i++) { adf_modeinfo_to_fb_videomode(&modelist[i], &fbmode); ret = fb_add_videomode(&fbmode, &fbdev->info->modelist); if (ret < 0) dev_warn(fbdev->info->dev, "adding mode %s to modelist failed: %d\n", modelist[i].name, ret); } kfree(modelist); }
/** * 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; }