[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