summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/drm_fb_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_fb_helper.c')
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c49
1 files changed, 34 insertions, 15 deletions
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 4b968f5b9c85..1b8f013ffa65 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -1821,17 +1821,6 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
if (ret < 0)
return ret;
- /*
- * Set the fb pointer - usually drm_setup_crtcs does this for hotplug
- * events, but at init time drm_setup_crtcs needs to be called before
- * the fb is allocated (since we need to figure out the desired size of
- * the fb before we can allocate it ...). Hence we need to fix things up
- * here again.
- */
- for (i = 0; i < fb_helper->crtc_count; i++)
- if (fb_helper->crtc_info[i].mode_set.num_connectors)
- fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb;
-
return 0;
}
@@ -1893,8 +1882,6 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe
info->var.xoffset = 0;
info->var.yoffset = 0;
info->var.activate = FB_ACTIVATE_NOW;
- info->var.height = -1;
- info->var.width = -1;
switch (fb->format->depth) {
case 8:
@@ -2410,9 +2397,9 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
struct drm_display_mode *mode = modes[i];
struct drm_fb_helper_crtc *fb_crtc = crtcs[i];
struct drm_fb_offset *offset = &offsets[i];
- struct drm_mode_set *modeset = &fb_crtc->mode_set;
if (mode && fb_crtc) {
+ struct drm_mode_set *modeset = &fb_crtc->mode_set;
struct drm_connector *connector =
fb_helper->connector_info[i]->connector;
@@ -2426,7 +2413,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
fb_crtc->desired_mode);
drm_connector_get(connector);
modeset->connectors[modeset->num_connectors++] = connector;
- modeset->fb = fb_helper->fb;
modeset->x = offset->x;
modeset->y = offset->y;
}
@@ -2438,6 +2424,37 @@ out:
kfree(enabled);
}
+/*
+ * This is a continuation of drm_setup_crtcs() that sets up anything related
+ * to the framebuffer. During initialization, drm_setup_crtcs() is called before
+ * the framebuffer has been allocated (fb_helper->fb and fb_helper->fbdev).
+ * So, any setup that touches those fields needs to be done here instead of in
+ * drm_setup_crtcs().
+ */
+static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper)
+{
+ struct fb_info *info = fb_helper->fbdev;
+ int i;
+
+ for (i = 0; i < fb_helper->crtc_count; i++)
+ if (fb_helper->crtc_info[i].mode_set.num_connectors)
+ fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb;
+
+ mutex_lock(&fb_helper->dev->mode_config.mutex);
+ drm_fb_helper_for_each_connector(fb_helper, i) {
+ struct drm_connector *connector =
+ fb_helper->connector_info[i]->connector;
+
+ /* use first connected connector for the physical dimensions */
+ if (connector->status == connector_status_connected) {
+ info->var.width = connector->display_info.width_mm;
+ info->var.height = connector->display_info.height_mm;
+ break;
+ }
+ }
+ mutex_unlock(&fb_helper->dev->mode_config.mutex);
+}
+
/* Note: Drops fb_helper->lock before returning. */
static int
__drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper,
@@ -2463,6 +2480,7 @@ __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper,
return ret;
}
+ drm_setup_crtcs_fb(fb_helper);
fb_helper->deferred_setup = false;
@@ -2591,6 +2609,7 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
DRM_DEBUG_KMS("\n");
drm_setup_crtcs(fb_helper, fb_helper->fb->width, fb_helper->fb->height);
+ drm_setup_crtcs_fb(fb_helper);
mutex_unlock(&fb_helper->lock);
drm_fb_helper_set_par(fb_helper->fbdev);