aboutsummaryrefslogtreecommitdiffstats
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.c45
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
1139static struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, int width, int height) 1135struct 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}
1148EXPORT_SYMBOL(drm_has_preferred_mode);
1152 1149
1153static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector) 1150static 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
1160static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn, 1157struct 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
1194create_mode: 1202create_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}
1208EXPORT_SYMBOL(drm_pick_cmdline_mode);
1200 1209
1201static bool drm_connector_enabled(struct drm_connector *connector, bool strict) 1210static 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 */