diff --git a/drivers/gpu/drm/clients/drm_fbdev_client.c b/drivers/gpu/drm/clients/drm_fbdev_client.c index 91d196a397cf..827f32668714 100644 --- a/drivers/gpu/drm/clients/drm_fbdev_client.c +++ b/drivers/gpu/drm/clients/drm_fbdev_client.c @@ -47,6 +47,14 @@ static int drm_fbdev_client_restore(struct drm_client_dev *client, bool force) return 0; } +static void drm_fbdev_client_acquire_outputs(struct drm_client_dev *client) +{ + struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); + + if (fb_helper->info) + fb_switch_outputs(fb_helper->info); +} + static int drm_fbdev_client_hotplug(struct drm_client_dev *client) { struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); @@ -95,13 +103,14 @@ static int drm_fbdev_client_resume(struct drm_client_dev *client) } static const struct drm_client_funcs drm_fbdev_client_funcs = { - .owner = THIS_MODULE, - .free = drm_fbdev_client_free, - .unregister = drm_fbdev_client_unregister, - .restore = drm_fbdev_client_restore, - .hotplug = drm_fbdev_client_hotplug, - .suspend = drm_fbdev_client_suspend, - .resume = drm_fbdev_client_resume, + .owner = THIS_MODULE, + .free = drm_fbdev_client_free, + .unregister = drm_fbdev_client_unregister, + .restore = drm_fbdev_client_restore, + .acquire_outputs = drm_fbdev_client_acquire_outputs, + .hotplug = drm_fbdev_client_hotplug, + .suspend = drm_fbdev_client_suspend, + .resume = drm_fbdev_client_resume, }; /** diff --git a/drivers/gpu/drm/drm_client_event.c b/drivers/gpu/drm/drm_client_event.c index 7b3e362f7926..f0af584da23c 100644 --- a/drivers/gpu/drm/drm_client_event.c +++ b/drivers/gpu/drm/drm_client_event.c @@ -123,6 +123,24 @@ void drm_client_dev_restore(struct drm_device *dev, bool force) mutex_unlock(&dev->clientlist_mutex); } +void drm_client_dev_acquire_outputs(struct drm_device *dev) +{ + struct drm_client_dev *client; + + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return; + + mutex_lock(&dev->clientlist_mutex); + list_for_each_entry(client, &dev->clientlist, list) { + if (!client->funcs || !client->funcs->acquire_outputs) + continue; + + client->funcs->acquire_outputs(client); + } + mutex_unlock(&dev->clientlist_mutex); +} +EXPORT_SYMBOL(drm_client_dev_acquire_outputs); + static int drm_client_suspend(struct drm_client_dev *client) { struct drm_device *dev = client->dev; diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h index 49a21f3dcb36..10a0cae3e48f 100644 --- a/include/drm/drm_client.h +++ b/include/drm/drm_client.h @@ -66,6 +66,20 @@ struct drm_client_funcs { */ int (*restore)(struct drm_client_dev *client, bool force); + /** + * @acquire_outputs: + * + * Called by vga-switcheroo. Informs the client that the outputs will + * be switched to its device. When @acquire_outputs runs, the outputs + * have not been switched yet. The client should only prepare the software + * state. After the switch happened, the client might get a hotplug + * event to update the hardware state. + * + * This callback exists for remapping framebuffers to virtual terminals + * in fbcon. + */ + void (*acquire_outputs)(struct drm_client_dev *client); + /** * @hotplug: * diff --git a/include/drm/drm_client_event.h b/include/drm/drm_client_event.h index 79369c755bc9..c93f404bae1d 100644 --- a/include/drm/drm_client_event.h +++ b/include/drm/drm_client_event.h @@ -11,6 +11,7 @@ struct drm_device; void drm_client_dev_unregister(struct drm_device *dev); void drm_client_dev_hotplug(struct drm_device *dev); void drm_client_dev_restore(struct drm_device *dev, bool force); +void drm_client_dev_acquire_outputs(struct drm_device *dev); void drm_client_dev_suspend(struct drm_device *dev); void drm_client_dev_resume(struct drm_device *dev); #else @@ -20,6 +21,8 @@ static inline void drm_client_dev_hotplug(struct drm_device *dev) { } static inline void drm_client_dev_restore(struct drm_device *dev, bool force) { } +static inline void drm_client_dev_acquire_outputs(struct drm_device *dev) +{ } static inline void drm_client_dev_suspend(struct drm_device *dev) { } static inline void drm_client_dev_resume(struct drm_device *dev)