@@ -35,6 +35,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <drm/drmP.h>
+#include <drm/drm_client.h>
#include <drm/drm_crtc.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_crtc_helper.h>
@@ -321,13 +322,14 @@ static bool drm_fb_helper_panel_rotation(struct drm_connector *connector,
return true;
}
-static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool active)
+static int drm_client_display_restore_atomic(struct drm_client_display *display, bool active)
{
- struct drm_device *dev = fb_helper->dev;
+ struct drm_device *dev = display->dev;
struct drm_plane_state *plane_state;
+ struct drm_mode_set *mode_set;
struct drm_plane *plane;
struct drm_atomic_state *state;
- int i, ret;
+ int ret;
unsigned int plane_mask;
struct drm_modeset_acquire_ctx ctx;
@@ -363,8 +365,7 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ
goto out_state;
}
- for (i = 0; i < fb_helper->crtc_count; i++) {
- struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
+ drm_client_display_for_each_modeset(mode_set, display) {
struct drm_plane *primary = mode_set->crtc->primary;
unsigned int rotation;
@@ -412,13 +413,14 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ
goto retry;
}
-static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper)
+static int drm_client_display_restore_legacy(struct drm_client_display *display)
{
- struct drm_device *dev = fb_helper->dev;
+ struct drm_device *dev = display->dev;
+ struct drm_mode_set *mode_set;
struct drm_plane *plane;
- int i, ret = 0;
+ int ret = 0;
- drm_modeset_lock_all(fb_helper->dev);
+ drm_modeset_lock_all(dev);
drm_for_each_plane(plane, dev) {
if (plane->type != DRM_PLANE_TYPE_PRIMARY)
drm_plane_force_disable(plane);
@@ -429,8 +431,7 @@ static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper)
DRM_MODE_ROTATE_0);
}
- for (i = 0; i < fb_helper->crtc_count; i++) {
- struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
+ drm_client_display_for_each_modeset(mode_set, display) {
struct drm_crtc *crtc = mode_set->crtc;
if (crtc->funcs->cursor_set2) {
@@ -448,19 +449,17 @@ static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper)
goto out;
}
out:
- drm_modeset_unlock_all(fb_helper->dev);
+ drm_modeset_unlock_all(dev);
return ret;
}
-static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
+static int drm_client_display_restore(struct drm_client_display *display)
{
- struct drm_device *dev = fb_helper->dev;
-
- if (drm_drv_uses_atomic_modeset(dev))
- return restore_fbdev_mode_atomic(fb_helper, true);
+ if (drm_drv_uses_atomic_modeset(display->dev))
+ return drm_client_display_restore_atomic(display, true);
else
- return restore_fbdev_mode_legacy(fb_helper);
+ return drm_client_display_restore_legacy(display);
}
/**
@@ -486,7 +485,7 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
return 0;
mutex_lock(&fb_helper->lock);
- ret = restore_fbdev_mode(fb_helper);
+ ret = drm_client_display_restore(fb_helper->display);
do_delayed = fb_helper->delayed_hotplug;
if (do_delayed)
@@ -548,7 +547,7 @@ static bool drm_fb_helper_force_kernel_mode(void)
continue;
mutex_lock(&helper->lock);
- ret = restore_fbdev_mode(helper);
+ ret = drm_client_display_restore(helper->display);
if (ret)
error = true;
mutex_unlock(&helper->lock);
@@ -580,22 +579,20 @@ static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = {
static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { };
#endif
-static void dpms_legacy(struct drm_fb_helper *fb_helper, int dpms_mode)
+static void drm_client_display_dpms_legacy(struct drm_client_display *display, int dpms_mode)
{
- struct drm_device *dev = fb_helper->dev;
+ struct drm_device *dev = display->dev;
struct drm_connector *connector;
struct drm_mode_set *modeset;
- int i, j;
+ int i;
drm_modeset_lock_all(dev);
- for (i = 0; i < fb_helper->crtc_count; i++) {
- modeset = &fb_helper->crtc_info[i].mode_set;
-
+ drm_client_display_for_each_modeset(modeset, display) {
if (!modeset->crtc->enabled)
continue;
- for (j = 0; j < modeset->num_connectors; j++) {
- connector = modeset->connectors[j];
+ for (i = 0; i < modeset->num_connectors; i++) {
+ connector = modeset->connectors[i];
connector->funcs->dpms(connector, dpms_mode);
drm_object_property_set_value(&connector->base,
dev->mode_config.dpms_property, dpms_mode);
@@ -604,23 +601,21 @@ static void dpms_legacy(struct drm_fb_helper *fb_helper, int dpms_mode)
drm_modeset_unlock_all(dev);
}
+static void drm_client_display_dpms(struct drm_client_display *display, int mode)
+{
+ if (drm_drv_uses_atomic_modeset(display->dev))
+ drm_client_display_restore_atomic(display, mode == DRM_MODE_DPMS_ON);
+ else
+ drm_client_display_dpms_legacy(display, mode);
+}
+
static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
{
struct drm_fb_helper *fb_helper = info->par;
- /*
- * For each CRTC in this fb, turn the connectors on/off.
- */
mutex_lock(&fb_helper->lock);
- if (!drm_fb_helper_is_bound(fb_helper)) {
- mutex_unlock(&fb_helper->lock);
- return;
- }
-
- if (drm_drv_uses_atomic_modeset(fb_helper->dev))
- restore_fbdev_mode_atomic(fb_helper, dpms_mode == DRM_MODE_DPMS_ON);
- else
- dpms_legacy(fb_helper, dpms_mode);
+ if (drm_fb_helper_is_bound(fb_helper))
+ drm_client_display_dpms(fb_helper->display, dpms_mode);
mutex_unlock(&fb_helper->lock);
}
@@ -811,6 +806,10 @@ int drm_fb_helper_init(struct drm_device *dev,
i++;
}
+ fb_helper->display = drm_client_display_create(dev);
+ if (IS_ERR(fb_helper->display))
+ goto out_free;
+
dev->fb_helper = fb_helper;
return 0;
@@ -919,6 +918,7 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
mutex_unlock(&kernel_fb_helper_lock);
mutex_destroy(&fb_helper->lock);
+ drm_client_display_free(fb_helper->display);
drm_fb_helper_crtc_free(fb_helper);
}
@@ -1265,13 +1265,14 @@ static int setcmap_pseudo_palette(struct fb_cmap *cmap, struct fb_info *info)
static int setcmap_legacy(struct fb_cmap *cmap, struct fb_info *info)
{
struct drm_fb_helper *fb_helper = info->par;
+ struct drm_mode_set *modeset;
struct drm_crtc *crtc;
u16 *r, *g, *b;
- int i, ret = 0;
+ int ret = 0;
drm_modeset_lock_all(fb_helper->dev);
- for (i = 0; i < fb_helper->crtc_count; i++) {
- crtc = fb_helper->crtc_info[i].mode_set.crtc;
+ drm_client_display_for_each_modeset(modeset, fb_helper->display) {
+ crtc = modeset->crtc;
if (!crtc->funcs->gamma_set || !crtc->gamma_size)
return -EINVAL;
@@ -1347,9 +1348,10 @@ static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info)
struct drm_modeset_acquire_ctx ctx;
struct drm_crtc_state *crtc_state;
struct drm_atomic_state *state;
+ struct drm_mode_set *modeset;
struct drm_crtc *crtc;
u16 *r, *g, *b;
- int i, ret = 0;
+ int ret = 0;
bool replaced;
drm_modeset_acquire_init(&ctx, 0);
@@ -1362,8 +1364,8 @@ static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info)
state->acquire_ctx = &ctx;
retry:
- for (i = 0; i < fb_helper->crtc_count; i++) {
- crtc = fb_helper->crtc_info[i].mode_set.crtc;
+ drm_client_display_for_each_modeset(modeset, fb_helper->display) {
+ crtc = modeset->crtc;
if (!gamma_lut)
gamma_lut = setcmap_new_gamma_lut(crtc, cmap);
@@ -1391,8 +1393,8 @@ static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info)
if (ret)
goto out_state;
- for (i = 0; i < fb_helper->crtc_count; i++) {
- crtc = fb_helper->crtc_info[i].mode_set.crtc;
+ drm_client_display_for_each_modeset(modeset, fb_helper->display) {
+ crtc = modeset->crtc;
r = crtc->gamma_store;
g = r + crtc->gamma_size;
@@ -1468,7 +1470,6 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg)
{
struct drm_fb_helper *fb_helper = info->par;
- struct drm_mode_set *mode_set;
struct drm_crtc *crtc;
int ret = 0;
@@ -1496,8 +1497,7 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
* make. If we're not smart enough here, one should
* just consider switch the userspace to KMS.
*/
- mode_set = &fb_helper->crtc_info[0].mode_set;
- crtc = mode_set->crtc;
+ crtc = fb_helper->display->modesets[0].crtc;
/*
* Only wait for a vblank event if the CRTC is
@@ -1651,13 +1651,9 @@ EXPORT_SYMBOL(drm_fb_helper_set_par);
static void pan_set(struct drm_fb_helper *fb_helper, int x, int y)
{
- int i;
-
- for (i = 0; i < fb_helper->crtc_count; i++) {
- struct drm_mode_set *mode_set;
-
- mode_set = &fb_helper->crtc_info[i].mode_set;
+ struct drm_mode_set *mode_set;
+ drm_client_display_for_each_modeset(mode_set, fb_helper->display) {
mode_set->x = x;
mode_set->y = y;
}
@@ -1671,7 +1667,7 @@ static int pan_display_atomic(struct fb_var_screeninfo *var,
pan_set(fb_helper, var->xoffset, var->yoffset);
- ret = restore_fbdev_mode_atomic(fb_helper, true);
+ ret = drm_client_display_restore(fb_helper->display);
if (!ret) {
info->var.xoffset = var->xoffset;
info->var.yoffset = var->yoffset;
@@ -1687,12 +1683,9 @@ static int pan_display_legacy(struct fb_var_screeninfo *var,
struct drm_fb_helper *fb_helper = info->par;
struct drm_mode_set *modeset;
int ret = 0;
- int i;
drm_modeset_lock_all(fb_helper->dev);
- for (i = 0; i < fb_helper->crtc_count; i++) {
- modeset = &fb_helper->crtc_info[i].mode_set;
-
+ drm_client_display_for_each_modeset(modeset, fb_helper->display) {
modeset->x = var->xoffset;
modeset->y = var->yoffset;
@@ -1751,6 +1744,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
int crtc_count = 0;
int i;
struct drm_fb_helper_surface_size sizes;
+ struct drm_mode_set *mode_set;
int gamma_size = 0;
memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size));
@@ -1795,9 +1789,8 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
}
crtc_count = 0;
- for (i = 0; i < fb_helper->crtc_count; i++) {
+ drm_client_display_for_each_modeset(mode_set, fb_helper->display) {
struct drm_display_mode *desired_mode;
- struct drm_mode_set *mode_set;
int x, y, j;
/* in case of tile group, are we the last tile vert or horiz?
* If no tile group you are always the last one both vertically
@@ -1805,19 +1798,18 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
*/
bool lastv = true, lasth = true;
- desired_mode = fb_helper->crtc_info[i].desired_mode;
- mode_set = &fb_helper->crtc_info[i].mode_set;
+ desired_mode = mode_set->mode;
if (!desired_mode)
continue;
crtc_count++;
- x = fb_helper->crtc_info[i].x;
- y = fb_helper->crtc_info[i].y;
+ x = mode_set->x;
+ y = mode_set->y;
if (gamma_size == 0)
- gamma_size = fb_helper->crtc_info[i].mode_set.crtc->gamma_size;
+ gamma_size = mode_set->crtc->gamma_size;
sizes.surface_width = max_t(u32, desired_mode->hdisplay + x, sizes.surface_width);
sizes.surface_height = max_t(u32, desired_mode->vdisplay + y, sizes.surface_height);
@@ -1844,7 +1836,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
/* First time: disable all crtc's.. */
if (!fb_helper->deferred_setup && !READ_ONCE(fb_helper->dev->master))
- restore_fbdev_mode(fb_helper);
+ drm_client_display_restore(fb_helper->display);
return -EAGAIN;
}
@@ -2379,6 +2371,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
u32 width, u32 height)
{
struct drm_device *dev = fb_helper->dev;
+ struct drm_client_display *display;
struct drm_fb_helper_crtc **crtcs;
struct drm_display_mode **modes;
struct drm_fb_offset *offsets;
@@ -2402,6 +2395,10 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
goto out;
}
+ display = drm_client_display_create(dev);
+ if (IS_ERR(display))
+ goto out;
+
mutex_lock(&fb_helper->dev->mode_config.mutex);
if (drm_fb_helper_probe_connector_modes(fb_helper, width, height) == 0)
DRM_DEBUG_KMS("No connectors reported connected with modes\n");
@@ -2440,24 +2437,29 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
struct drm_fb_offset *offset = &offsets[i];
if (mode && fb_crtc) {
- struct drm_mode_set *modeset = &fb_crtc->mode_set;
struct drm_connector *connector =
fb_helper->connector_info[i]->connector;
+ struct drm_mode_set *modeset;
+
+ modeset = drm_client_display_find_modeset(display, fb_crtc->mode_set.crtc);
+ if (WARN_ON(!modeset)) {
+ drm_client_display_free(display);
+ goto out;
+ }
DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n",
- mode->name, fb_crtc->mode_set.crtc->base.id, offset->x, offset->y);
+ mode->name, modeset->crtc->base.id, offset->x, offset->y);
- fb_crtc->desired_mode = mode;
- fb_crtc->x = offset->x;
- fb_crtc->y = offset->y;
- modeset->mode = drm_mode_duplicate(dev,
- fb_crtc->desired_mode);
+ modeset->mode = drm_mode_duplicate(dev, mode);
drm_connector_get(connector);
modeset->connectors[modeset->num_connectors++] = connector;
modeset->x = offset->x;
modeset->y = offset->y;
}
}
+
+ drm_client_display_free(fb_helper->display);
+ fb_helper->display = display;
out:
kfree(crtcs);
kfree(modes);
@@ -2476,11 +2478,10 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper)
{
struct fb_info *info = fb_helper->fbdev;
unsigned int rotation, sw_rotations = 0;
+ struct drm_mode_set *modeset;
int i;
- for (i = 0; i < fb_helper->crtc_count; i++) {
- struct drm_mode_set *modeset = &fb_helper->crtc_info[i].mode_set;
-
+ drm_client_display_for_each_modeset(modeset, fb_helper->display) {
if (!modeset->num_connectors)
continue;
@@ -155,6 +155,14 @@ struct drm_fb_helper_connector {
struct drm_fb_helper {
struct drm_framebuffer *fb;
struct drm_device *dev;
+
+ /**
+ * @display:
+ *
+ * Display representation.
+ */
+ struct drm_client_display *display;
+
int crtc_count;
struct drm_fb_helper_crtc *crtc_info;
int connector_count;
Prepare to move the modeset committing code to drm_client. Signed-off-by: Noralf Trønnes <noralf@tronnes.org> --- drivers/gpu/drm/drm_fb_helper.c | 161 ++++++++++++++++++++-------------------- include/drm/drm_fb_helper.h | 8 ++ 2 files changed, 89 insertions(+), 80 deletions(-)