[PATCH 09/20] drm fb_helper: use lists for crtcs.

Sascha Hauer s.hauer at pengutronix.de
Wed Feb 1 02:38:27 PST 2012


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 at pengutronix.de>
---
 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



More information about the dri-devel mailing list