diff options
Diffstat (limited to 'drivers/gpu/drm/drm_fb_helper.c')
-rw-r--r-- | drivers/gpu/drm/drm_fb_helper.c | 45 |
1 files changed, 28 insertions, 17 deletions
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 98a03639b413..04d3fd3658f3 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c | |||
@@ -232,7 +232,7 @@ static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc) | |||
232 | 232 | ||
233 | list_for_each_entry(c, &dev->mode_config.crtc_list, head) { | 233 | list_for_each_entry(c, &dev->mode_config.crtc_list, head) { |
234 | if (crtc->base.id == c->base.id) | 234 | if (crtc->base.id == c->base.id) |
235 | return c->fb; | 235 | return c->primary->fb; |
236 | } | 236 | } |
237 | 237 | ||
238 | return NULL; | 238 | return NULL; |
@@ -291,7 +291,8 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper) | |||
291 | drm_warn_on_modeset_not_all_locked(dev); | 291 | drm_warn_on_modeset_not_all_locked(dev); |
292 | 292 | ||
293 | list_for_each_entry(plane, &dev->mode_config.plane_list, head) | 293 | list_for_each_entry(plane, &dev->mode_config.plane_list, head) |
294 | drm_plane_force_disable(plane); | 294 | if (plane->type != DRM_PLANE_TYPE_PRIMARY) |
295 | drm_plane_force_disable(plane); | ||
295 | 296 | ||
296 | for (i = 0; i < fb_helper->crtc_count; i++) { | 297 | for (i = 0; i < fb_helper->crtc_count; i++) { |
297 | struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; | 298 | struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; |
@@ -365,9 +366,9 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper) | |||
365 | return false; | 366 | return false; |
366 | 367 | ||
367 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 368 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
368 | if (crtc->fb) | 369 | if (crtc->primary->fb) |
369 | crtcs_bound++; | 370 | crtcs_bound++; |
370 | if (crtc->fb == fb_helper->fb) | 371 | if (crtc->primary->fb == fb_helper->fb) |
371 | bound++; | 372 | bound++; |
372 | } | 373 | } |
373 | 374 | ||
@@ -516,6 +517,9 @@ int drm_fb_helper_init(struct drm_device *dev, | |||
516 | struct drm_crtc *crtc; | 517 | struct drm_crtc *crtc; |
517 | int i; | 518 | int i; |
518 | 519 | ||
520 | if (!max_conn_count) | ||
521 | return -EINVAL; | ||
522 | |||
519 | fb_helper->dev = dev; | 523 | fb_helper->dev = dev; |
520 | 524 | ||
521 | INIT_LIST_HEAD(&fb_helper->kernel_fb_list); | 525 | INIT_LIST_HEAD(&fb_helper->kernel_fb_list); |
@@ -809,8 +813,6 @@ int drm_fb_helper_set_par(struct fb_info *info) | |||
809 | struct drm_fb_helper *fb_helper = info->par; | 813 | struct drm_fb_helper *fb_helper = info->par; |
810 | struct drm_device *dev = fb_helper->dev; | 814 | struct drm_device *dev = fb_helper->dev; |
811 | struct fb_var_screeninfo *var = &info->var; | 815 | struct fb_var_screeninfo *var = &info->var; |
812 | int ret; | ||
813 | int i; | ||
814 | 816 | ||
815 | if (var->pixclock != 0) { | 817 | if (var->pixclock != 0) { |
816 | DRM_ERROR("PIXEL CLOCK SET\n"); | 818 | DRM_ERROR("PIXEL CLOCK SET\n"); |
@@ -818,13 +820,7 @@ int drm_fb_helper_set_par(struct fb_info *info) | |||
818 | } | 820 | } |
819 | 821 | ||
820 | drm_modeset_lock_all(dev); | 822 | drm_modeset_lock_all(dev); |
821 | for (i = 0; i < fb_helper->crtc_count; i++) { | 823 | drm_fb_helper_restore_fbdev_mode(fb_helper); |
822 | ret = drm_mode_set_config_internal(&fb_helper->crtc_info[i].mode_set); | ||
823 | if (ret) { | ||
824 | drm_modeset_unlock_all(dev); | ||
825 | return ret; | ||
826 | } | ||
827 | } | ||
828 | drm_modeset_unlock_all(dev); | 824 | drm_modeset_unlock_all(dev); |
829 | 825 | ||
830 | if (fb_helper->delayed_hotplug) { | 826 | if (fb_helper->delayed_hotplug) { |
@@ -1136,19 +1132,20 @@ static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper, | |||
1136 | return count; | 1132 | return count; |
1137 | } | 1133 | } |
1138 | 1134 | ||
1139 | static struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, int width, int height) | 1135 | struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, int width, int height) |
1140 | { | 1136 | { |
1141 | struct drm_display_mode *mode; | 1137 | struct drm_display_mode *mode; |
1142 | 1138 | ||
1143 | list_for_each_entry(mode, &fb_connector->connector->modes, head) { | 1139 | list_for_each_entry(mode, &fb_connector->connector->modes, head) { |
1144 | if (drm_mode_width(mode) > width || | 1140 | if (mode->hdisplay > width || |
1145 | drm_mode_height(mode) > height) | 1141 | mode->vdisplay > height) |
1146 | continue; | 1142 | continue; |
1147 | if (mode->type & DRM_MODE_TYPE_PREFERRED) | 1143 | if (mode->type & DRM_MODE_TYPE_PREFERRED) |
1148 | return mode; | 1144 | return mode; |
1149 | } | 1145 | } |
1150 | return NULL; | 1146 | return NULL; |
1151 | } | 1147 | } |
1148 | EXPORT_SYMBOL(drm_has_preferred_mode); | ||
1152 | 1149 | ||
1153 | static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector) | 1150 | static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector) |
1154 | { | 1151 | { |
@@ -1157,11 +1154,12 @@ static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector) | |||
1157 | return cmdline_mode->specified; | 1154 | return cmdline_mode->specified; |
1158 | } | 1155 | } |
1159 | 1156 | ||
1160 | static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn, | 1157 | struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn, |
1161 | int width, int height) | 1158 | int width, int height) |
1162 | { | 1159 | { |
1163 | struct drm_cmdline_mode *cmdline_mode; | 1160 | struct drm_cmdline_mode *cmdline_mode; |
1164 | struct drm_display_mode *mode = NULL; | 1161 | struct drm_display_mode *mode = NULL; |
1162 | bool prefer_non_interlace; | ||
1165 | 1163 | ||
1166 | cmdline_mode = &fb_helper_conn->cmdline_mode; | 1164 | cmdline_mode = &fb_helper_conn->cmdline_mode; |
1167 | if (cmdline_mode->specified == false) | 1165 | if (cmdline_mode->specified == false) |
@@ -1173,6 +1171,8 @@ static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_conne | |||
1173 | if (cmdline_mode->rb || cmdline_mode->margins) | 1171 | if (cmdline_mode->rb || cmdline_mode->margins) |
1174 | goto create_mode; | 1172 | goto create_mode; |
1175 | 1173 | ||
1174 | prefer_non_interlace = !cmdline_mode->interlace; | ||
1175 | again: | ||
1176 | list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) { | 1176 | list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) { |
1177 | /* check width/height */ | 1177 | /* check width/height */ |
1178 | if (mode->hdisplay != cmdline_mode->xres || | 1178 | if (mode->hdisplay != cmdline_mode->xres || |
@@ -1187,16 +1187,25 @@ static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_conne | |||
1187 | if (cmdline_mode->interlace) { | 1187 | if (cmdline_mode->interlace) { |
1188 | if (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) | 1188 | if (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) |
1189 | continue; | 1189 | continue; |
1190 | } else if (prefer_non_interlace) { | ||
1191 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) | ||
1192 | continue; | ||
1190 | } | 1193 | } |
1191 | return mode; | 1194 | return mode; |
1192 | } | 1195 | } |
1193 | 1196 | ||
1197 | if (prefer_non_interlace) { | ||
1198 | prefer_non_interlace = false; | ||
1199 | goto again; | ||
1200 | } | ||
1201 | |||
1194 | create_mode: | 1202 | create_mode: |
1195 | mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev, | 1203 | mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev, |
1196 | cmdline_mode); | 1204 | cmdline_mode); |
1197 | list_add(&mode->head, &fb_helper_conn->connector->modes); | 1205 | list_add(&mode->head, &fb_helper_conn->connector->modes); |
1198 | return mode; | 1206 | return mode; |
1199 | } | 1207 | } |
1208 | EXPORT_SYMBOL(drm_pick_cmdline_mode); | ||
1200 | 1209 | ||
1201 | static bool drm_connector_enabled(struct drm_connector *connector, bool strict) | 1210 | static bool drm_connector_enabled(struct drm_connector *connector, bool strict) |
1202 | { | 1211 | { |
@@ -1539,9 +1548,11 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) | |||
1539 | 1548 | ||
1540 | drm_fb_helper_parse_command_line(fb_helper); | 1549 | drm_fb_helper_parse_command_line(fb_helper); |
1541 | 1550 | ||
1551 | mutex_lock(&dev->mode_config.mutex); | ||
1542 | count = drm_fb_helper_probe_connector_modes(fb_helper, | 1552 | count = drm_fb_helper_probe_connector_modes(fb_helper, |
1543 | dev->mode_config.max_width, | 1553 | dev->mode_config.max_width, |
1544 | dev->mode_config.max_height); | 1554 | dev->mode_config.max_height); |
1555 | mutex_unlock(&dev->mode_config.mutex); | ||
1545 | /* | 1556 | /* |
1546 | * we shouldn't end up with no modes here. | 1557 | * we shouldn't end up with no modes here. |
1547 | */ | 1558 | */ |