The fb helper uses fixed size arrays for the associated crtcs. This is an unnecessary limitation, so instead use a list to store the crtcs and allocate them dynamically. Signed-off-by: Sascha Hauer <s.hauer@xxxxxxxxxxxxxx> --- drivers/gpu/drm/drm_fb_helper.c | 129 ++++++++++++++++++++------------------- include/drm/drm_fb_helper.h | 3 +- 2 files changed, 68 insertions(+), 64 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 7740dd2..f292a78 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -147,15 +147,14 @@ int drm_fb_helper_debug_enter(struct fb_info *info) { struct drm_fb_helper *helper = info->par; struct drm_crtc_helper_funcs *funcs; - int i; if (list_empty(&kernel_fb_helper_list)) return false; list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) { - for (i = 0; i < helper->crtc_count; i++) { - struct drm_mode_set *mode_set = - &helper->crtc_info[i].mode_set; + struct drm_fb_helper_crtc *helper_crtc; + list_for_each_entry(helper_crtc, &helper->crtc_list, list) { + struct drm_mode_set *mode_set = &helper_crtc->mode_set; if (!mode_set->crtc->enabled) continue; @@ -194,10 +193,10 @@ int drm_fb_helper_debug_leave(struct fb_info *info) struct drm_crtc *crtc; struct drm_crtc_helper_funcs *funcs; struct drm_framebuffer *fb; - int i; + struct drm_fb_helper_crtc *helper_crtc; - for (i = 0; i < helper->crtc_count; i++) { - struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set; + list_for_each_entry(helper_crtc, &helper->crtc_list, list) { + struct drm_mode_set *mode_set = &helper_crtc->mode_set; crtc = mode_set->crtc; funcs = crtc->helper_private; fb = drm_mode_config_fb(crtc); @@ -221,10 +220,12 @@ EXPORT_SYMBOL(drm_fb_helper_debug_leave); bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper) { + struct drm_fb_helper_crtc *helper_crtc; bool error = false; - int i, ret; - for (i = 0; i < fb_helper->crtc_count; i++) { - struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; + int ret; + + list_for_each_entry(helper_crtc, &fb_helper->crtc_list, list) { + struct drm_mode_set *mode_set = &helper_crtc->mode_set; ret = drm_crtc_helper_set_config(mode_set); if (ret) error = true; @@ -312,14 +313,15 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) struct drm_device *dev = fb_helper->dev; struct drm_crtc *crtc; struct drm_connector *connector; - int i, j; + struct drm_fb_helper_crtc *helper_crtc; + int j; /* * For each CRTC in this fb, turn the connectors on/off. */ mutex_lock(&dev->mode_config.mutex); - for (i = 0; i < fb_helper->crtc_count; i++) { - crtc = fb_helper->crtc_info[i].mode_set.crtc; + list_for_each_entry(helper_crtc, &fb_helper->crtc_list, list) { + crtc = helper_crtc->mode_set.crtc; if (!crtc->enabled) continue; @@ -365,17 +367,20 @@ EXPORT_SYMBOL(drm_fb_helper_blank); static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper) { + struct drm_fb_helper_crtc *helper_crtc, *tmp; int i; for (i = 0; i < helper->connector_count; i++) kfree(helper->connector_info[i]); + kfree(helper->connector_info); - for (i = 0; i < helper->crtc_count; i++) { - kfree(helper->crtc_info[i].mode_set.connectors); - if (helper->crtc_info[i].mode_set.mode) - drm_mode_destroy(helper->dev, helper->crtc_info[i].mode_set.mode); + + list_for_each_entry_safe(helper_crtc, tmp, &helper->crtc_list, list) { + kfree(helper_crtc->mode_set.connectors); + if (helper_crtc->mode_set.mode) + drm_mode_destroy(helper->dev, helper_crtc->mode_set.mode); + kfree(helper_crtc); } - kfree(helper->crtc_info); } int drm_fb_helper_init(struct drm_device *dev, @@ -383,42 +388,40 @@ int drm_fb_helper_init(struct drm_device *dev, int crtc_count, int max_conn_count) { struct drm_crtc *crtc; + struct drm_fb_helper_crtc *helper_crtc; int ret = 0; - int i; fb_helper->dev = dev; INIT_LIST_HEAD(&fb_helper->kernel_fb_list); + INIT_LIST_HEAD(&fb_helper->crtc_list); - fb_helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL); - if (!fb_helper->crtc_info) + fb_helper->crtc_count = 0; + fb_helper->connector_info = kcalloc(dev->mode_config.num_connector, + sizeof(struct drm_fb_helper_connector *), GFP_KERNEL); + if (!fb_helper->connector_info) return -ENOMEM; - fb_helper->crtc_count = crtc_count; - fb_helper->connector_info = kcalloc(dev->mode_config.num_connector, sizeof(struct drm_fb_helper_connector *), GFP_KERNEL); - if (!fb_helper->connector_info) { - kfree(fb_helper->crtc_info); - return -ENOMEM; - } fb_helper->connector_count = 0; - for (i = 0; i < crtc_count; i++) { - fb_helper->crtc_info[i].mode_set.connectors = + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + helper_crtc = kzalloc(sizeof(*helper_crtc), GFP_KERNEL); + if (!helper_crtc) + goto out_free; + + helper_crtc->mode_set.crtc = crtc; + helper_crtc->mode_set.connectors = kcalloc(max_conn_count, sizeof(struct drm_connector *), GFP_KERNEL); - if (!fb_helper->crtc_info[i].mode_set.connectors) { + if (!helper_crtc->mode_set.connectors) { ret = -ENOMEM; goto out_free; } - fb_helper->crtc_info[i].mode_set.num_connectors = 0; - } - - i = 0; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - fb_helper->crtc_info[i].mode_set.crtc = crtc; - i++; + helper_crtc->mode_set.num_connectors = 0; + list_add_tail(&helper_crtc->list, &fb_helper->crtc_list); + fb_helper->crtc_count++; } return 0; @@ -515,11 +518,12 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) struct drm_crtc_helper_funcs *crtc_funcs; u16 *red, *green, *blue, *transp; struct drm_crtc *crtc; - int i, j, rc = 0; + struct drm_fb_helper_crtc *helper_crtc; + int j, rc = 0; int start; - for (i = 0; i < fb_helper->crtc_count; i++) { - crtc = fb_helper->crtc_info[i].mode_set.crtc; + list_for_each_entry(helper_crtc, &fb_helper->crtc_list, list) { + crtc = helper_crtc->mode_set.crtc; crtc_funcs = crtc->helper_private; red = cmap->red; @@ -642,9 +646,9 @@ int drm_fb_helper_set_par(struct fb_info *info) struct drm_fb_helper *fb_helper = info->par; struct drm_device *dev = fb_helper->dev; struct fb_var_screeninfo *var = &info->var; + struct drm_fb_helper_crtc *helper_crtc; struct drm_crtc *crtc; int ret; - int i; if (var->pixclock != 0) { DRM_ERROR("PIXEL CLOCK SET\n"); @@ -652,9 +656,9 @@ int drm_fb_helper_set_par(struct fb_info *info) } mutex_lock(&dev->mode_config.mutex); - for (i = 0; i < fb_helper->crtc_count; i++) { - crtc = fb_helper->crtc_info[i].mode_set.crtc; - ret = crtc->funcs->set_config(&fb_helper->crtc_info[i].mode_set); + list_for_each_entry(helper_crtc, &fb_helper->crtc_list, list) { + crtc = helper_crtc->mode_set.crtc; + ret = crtc->funcs->set_config(&helper_crtc->mode_set); if (ret) { mutex_unlock(&dev->mode_config.mutex); return ret; @@ -676,15 +680,15 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, struct drm_fb_helper *fb_helper = info->par; struct drm_device *dev = fb_helper->dev; struct drm_mode_set *modeset; + struct drm_fb_helper_crtc *helper_crtc; struct drm_crtc *crtc; int ret = 0; - int i; mutex_lock(&dev->mode_config.mutex); - for (i = 0; i < fb_helper->crtc_count; i++) { - crtc = fb_helper->crtc_info[i].mode_set.crtc; + list_for_each_entry(helper_crtc, &fb_helper->crtc_list, list) { + modeset = &helper_crtc->mode_set; + crtc = modeset->crtc; - modeset = &fb_helper->crtc_info[i].mode_set; modeset->x = var->xoffset; modeset->y = var->yoffset; @@ -705,6 +709,7 @@ EXPORT_SYMBOL(drm_fb_helper_pan_display); int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, int preferred_bpp) { + struct drm_fb_helper_crtc *helper_crtc; int new_fb = 0; int crtc_count = 0; int i; @@ -755,13 +760,13 @@ 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++) { + list_for_each_entry(helper_crtc, &fb_helper->crtc_list, list) { struct drm_display_mode *desired_mode; - desired_mode = fb_helper->crtc_info[i].desired_mode; + desired_mode = helper_crtc->desired_mode; if (desired_mode) { if (gamma_size == 0) - gamma_size = fb_helper->crtc_info[i].mode_set.crtc->gamma_size; + gamma_size = helper_crtc->mode_set.crtc->gamma_size; if (desired_mode->hdisplay < sizes.fb_width) sizes.fb_width = desired_mode->hdisplay; if (desired_mode->vdisplay < sizes.fb_height) @@ -790,16 +795,15 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, info = fb_helper->fbdev; /* set the fb pointer */ - for (i = 0; i < fb_helper->crtc_count; i++) { - fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb; - } + list_for_each_entry(helper_crtc, &fb_helper->crtc_list, list) + helper_crtc->mode_set.fb = fb_helper->fb; if (new_fb) { info->var.pixclock = 0; if (register_framebuffer(info) < 0) { return -EINVAL; } - + drm_fb_helper_blank(FB_BLANK_UNBLANK, info); printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id); @@ -1184,12 +1188,13 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, /* select a crtc for this connector and then attempt to configure remaining connectors */ - for (c = 0; c < fb_helper->crtc_count; c++) { - crtc = &fb_helper->crtc_info[c]; - + c = 0; + list_for_each_entry(crtc, &fb_helper->crtc_list, list) { if ((encoder->possible_crtcs & (1 << c)) == 0) { + c++; continue; } + c++; for (o = 0; o < n; o++) if (best_crtcs[o] == crtc) @@ -1224,7 +1229,7 @@ out: static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) { struct drm_device *dev = fb_helper->dev; - struct drm_fb_helper_crtc **crtcs; + struct drm_fb_helper_crtc **crtcs, *helper_crtc; struct drm_display_mode **modes; struct drm_encoder *encoder; struct drm_mode_set *modeset; @@ -1264,10 +1269,8 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) /* need to set the modesets up here for use later */ /* fill out the connector<->crtc mappings into the modesets */ - for (i = 0; i < fb_helper->crtc_count; i++) { - modeset = &fb_helper->crtc_info[i].mode_set; - modeset->num_connectors = 0; - } + list_for_each_entry(helper_crtc, &fb_helper->crtc_list, list) + helper_crtc->mode_set.num_connectors = 0; for (i = 0; i < fb_helper->connector_count; i++) { struct drm_display_mode *mode = modes[i]; diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 5120b01..e1e1c02 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -37,6 +37,7 @@ struct drm_fb_helper; struct drm_fb_helper_crtc { struct drm_mode_set mode_set; struct drm_display_mode *desired_mode; + struct list_head list; }; struct drm_fb_helper_surface_size { @@ -69,7 +70,7 @@ struct drm_fb_helper { struct drm_device *dev; struct drm_display_mode *mode; int crtc_count; - struct drm_fb_helper_crtc *crtc_info; + struct list_head crtc_list; int connector_count; struct drm_fb_helper_connector **connector_info; struct drm_fb_helper_funcs *funcs; -- 1.7.8.3 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel