aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2013-01-21 04:52:17 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-02-13 18:07:55 -0500
commit7e53f3a423146745a4e4bb93362d488dfad502a8 (patch)
treeae842901c15126d09ceade149e8c1c72a6766a46 /drivers/gpu
parentaf5676f1f91585cabe811b8f697e32015e2be826 (diff)
drm/fb-helper: fixup set_config semantics
While doing the modeset rework for drm/i915 I've noticed that the fb helper is very liberal with the semantics of the ->set_config interface: - It doesn't bother clearing stale modes (e.g. when unplugging a screen). - It unconditionally sets the fb, even if no mode will be set on a given crtc. - The initial setup is a bit fun since we need to pick crtcs to decide the desired fb size, but also should set the modeset->fb pointer. Explain what's going on in the fixup code after the fb is allocated. The crtc helper didn't really care, but the new i915 modeset infrastructure did, so I've had to add a bunch of special-cases to catch this. Fix this all up and enforce the interface by converting the checks in drm/i915/intel_display.c to BUG_ONs. v2: Fix commit message spell fail spotted by Rob Clark. Reviewed-by: Rob Clark <robdclark@gmail.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c27
-rw-r--r--drivers/gpu/drm/i915/intel_display.c11
2 files changed, 26 insertions, 12 deletions
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index d841b68aaa3e..809ef99f910e 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -689,7 +689,6 @@ int drm_fb_helper_set_par(struct fb_info *info)
689 struct drm_fb_helper *fb_helper = info->par; 689 struct drm_fb_helper *fb_helper = info->par;
690 struct drm_device *dev = fb_helper->dev; 690 struct drm_device *dev = fb_helper->dev;
691 struct fb_var_screeninfo *var = &info->var; 691 struct fb_var_screeninfo *var = &info->var;
692 struct drm_crtc *crtc;
693 int ret; 692 int ret;
694 int i; 693 int i;
695 694
@@ -700,7 +699,6 @@ int drm_fb_helper_set_par(struct fb_info *info)
700 699
701 drm_modeset_lock_all(dev); 700 drm_modeset_lock_all(dev);
702 for (i = 0; i < fb_helper->crtc_count; i++) { 701 for (i = 0; i < fb_helper->crtc_count; i++) {
703 crtc = fb_helper->crtc_info[i].mode_set.crtc;
704 ret = drm_mode_set_config_internal(&fb_helper->crtc_info[i].mode_set); 702 ret = drm_mode_set_config_internal(&fb_helper->crtc_info[i].mode_set);
705 if (ret) { 703 if (ret) {
706 drm_modeset_unlock_all(dev); 704 drm_modeset_unlock_all(dev);
@@ -841,9 +839,17 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
841 839
842 info = fb_helper->fbdev; 840 info = fb_helper->fbdev;
843 841
844 /* set the fb pointer */ 842 /*
843 * Set the fb pointer - usually drm_setup_crtcs does this for hotplug
844 * events, but at init time drm_setup_crtcs needs to be called before
845 * the fb is allocated (since we need to figure out the desired size of
846 * the fb before we can allocate it ...). Hence we need to fix things up
847 * here again.
848 */
845 for (i = 0; i < fb_helper->crtc_count; i++) 849 for (i = 0; i < fb_helper->crtc_count; i++)
846 fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb; 850 if (fb_helper->crtc_info[i].mode_set.num_connectors)
851 fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb;
852
847 853
848 if (new_fb) { 854 if (new_fb) {
849 info->var.pixclock = 0; 855 info->var.pixclock = 0;
@@ -1314,6 +1320,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
1314 for (i = 0; i < fb_helper->crtc_count; i++) { 1320 for (i = 0; i < fb_helper->crtc_count; i++) {
1315 modeset = &fb_helper->crtc_info[i].mode_set; 1321 modeset = &fb_helper->crtc_info[i].mode_set;
1316 modeset->num_connectors = 0; 1322 modeset->num_connectors = 0;
1323 modeset->fb = NULL;
1317 } 1324 }
1318 1325
1319 for (i = 0; i < fb_helper->connector_count; i++) { 1326 for (i = 0; i < fb_helper->connector_count; i++) {
@@ -1330,9 +1337,21 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
1330 modeset->mode = drm_mode_duplicate(dev, 1337 modeset->mode = drm_mode_duplicate(dev,
1331 fb_crtc->desired_mode); 1338 fb_crtc->desired_mode);
1332 modeset->connectors[modeset->num_connectors++] = fb_helper->connector_info[i]->connector; 1339 modeset->connectors[modeset->num_connectors++] = fb_helper->connector_info[i]->connector;
1340 modeset->fb = fb_helper->fb;
1333 } 1341 }
1334 } 1342 }
1335 1343
1344 /* Clear out any old modes if there are no more connected outputs. */
1345 for (i = 0; i < fb_helper->crtc_count; i++) {
1346 modeset = &fb_helper->crtc_info[i].mode_set;
1347 if (modeset->num_connectors == 0) {
1348 BUG_ON(modeset->fb);
1349 BUG_ON(modeset->num_connectors);
1350 if (modeset->mode)
1351 drm_mode_destroy(dev, modeset->mode);
1352 modeset->mode = NULL;
1353 }
1354 }
1336out: 1355out:
1337 kfree(crtcs); 1356 kfree(crtcs);
1338 kfree(modes); 1357 kfree(modes);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 24f2654338d2..ca8d5929063e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7978,14 +7978,9 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
7978 BUG_ON(!set->crtc); 7978 BUG_ON(!set->crtc);
7979 BUG_ON(!set->crtc->helper_private); 7979 BUG_ON(!set->crtc->helper_private);
7980 7980
7981 if (!set->mode) 7981 /* Enforce sane interface api - has been abused by the fb helper. */
7982 set->fb = NULL; 7982 BUG_ON(!set->mode && set->fb);
7983 7983 BUG_ON(set->fb && set->num_connectors == 0);
7984 /* The fb helper likes to play gross jokes with ->mode_set_config.
7985 * Unfortunately the crtc helper doesn't do much at all for this case,
7986 * so we have to cope with this madness until the fb helper is fixed up. */
7987 if (set->fb && set->num_connectors == 0)
7988 return 0;
7989 7984
7990 if (set->fb) { 7985 if (set->fb) {
7991 DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n", 7986 DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",