intelfb: move mode sets into the intel crtcs
authorDave Airlie <airlied@linux.ie>
Fri, 6 Jun 2008 02:02:51 +0000 (12:02 +1000)
committerDave Airlie <airlied@linux.ie>
Fri, 6 Jun 2008 02:02:51 +0000 (12:02 +1000)
better place to store them.

linux-core/intel_display.c
linux-core/intel_drv.h
linux-core/intel_fb.c

index e2d2a5f..0081b5b 100644 (file)
@@ -1363,7 +1363,7 @@ void intel_crtc_init(struct drm_device *dev, int pipe)
        struct intel_crtc *intel_crtc;
        int i;
 
-       intel_crtc = kzalloc(sizeof(struct intel_crtc), GFP_KERNEL);
+       intel_crtc = kzalloc(sizeof(struct intel_crtc) + (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL);
        if (intel_crtc == NULL)
                return;
 
@@ -1381,6 +1381,10 @@ void intel_crtc_init(struct drm_device *dev, int pipe)
        intel_crtc->dpms_mode = DPMSModeOff;
        drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
 
+       intel_crtc->mode_set.crtc = &intel_crtc->base;
+       intel_crtc->mode_set.connectors = (struct drm_connector **)(intel_crtc + 1);
+       intel_crtc->mode_set.num_connectors = 0;
+
        if (i915_fbpercrtc) {
                
 
index 25e2a65..1008e27 100644 (file)
@@ -20,6 +20,8 @@
 /* The i830->i865 use multiple DVOs with multiple i2cs */
 /* the i915, i945 have a single sDVO i2c bus - which is different */
 #define MAX_OUTPUTS 6
+/* maximum connectors per crtcs in the mode set */
+#define INTELFB_CONN_LIMIT 4
 
 #define INTEL_I2C_BUS_DVO 1
 #define INTEL_I2C_BUS_SDVO 2
@@ -72,6 +74,8 @@ struct intel_crtc {
        u8 lut_r[256], lut_g[256], lut_b[256];
        int dpms_mode;
        struct intel_framebuffer *fbdev_fb;
+       /* a mode_set for fbdev users on this crtc */
+       struct drm_mode_set mode_set;
 };
 
 #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
index 5ec5bb8..71f71a0 100644 (file)
@@ -50,7 +50,8 @@ struct intelfb_par {
        struct drm_display_mode *our_mode;
        struct intel_framebuffer *intel_fb;
        int crtc_count;
-       struct list_head mode_set_list;
+       /* crtc currently bound to this */
+       uint32_t crtc_ids[2];
 };
 /*
 static int
@@ -69,12 +70,23 @@ static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
                        struct fb_info *info)
 {
        struct intelfb_par *par = info->par;
-       struct drm_mode_set *modeset;
+       struct drm_device *dev = par->dev;
+       struct drm_crtc *crtc;
+       int i;
 
-       list_for_each_entry(modeset, &par->mode_set_list, head) {
-               struct drm_crtc *crtc = modeset->crtc;
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+               struct drm_mode_set *modeset = &intel_crtc->mode_set;
                struct drm_framebuffer *fb = modeset->fb;
 
+               for (i = 0; i < par->crtc_count; i++)
+                       if (crtc->base.id == par->crtc_ids[i])
+                               break;
+
+               if (i == par->crtc_count)
+                       continue;
+               
+
                if (regno > 255)
                        return 1;
 
@@ -200,7 +212,9 @@ static int intelfb_check_var(struct fb_var_screeninfo *var,
 static int intelfb_set_par(struct fb_info *info)
 {
        struct intelfb_par *par = info->par;
+       struct drm_device *dev = par->dev;
        struct fb_var_screeninfo *var = &info->var;
+       int i;
 
        DRM_DEBUG("%d %d\n", var->xres, var->pixclock);
 
@@ -305,11 +319,20 @@ static int intelfb_set_par(struct fb_info *info)
 #endif
                return -EINVAL;
        } else {
-               struct drm_mode_set *modeset;
+               struct drm_crtc *crtc;
                int ret;
 
-               list_for_each_entry(modeset, &par->mode_set_list, head) {
-                       ret = modeset->crtc->funcs->set_config(modeset);
+               list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+                       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+                       for (i = 0; i < par->crtc_count; i++)
+                               if (crtc->base.id == par->crtc_ids[i])
+                                       break;
+
+                       if (i == par->crtc_count)
+                               continue;
+
+                       ret = crtc->funcs->set_config(&intel_crtc->mode_set);
                        if (ret)
                                return ret;
                }
@@ -466,15 +489,30 @@ static int intelfb_pan_display(struct fb_var_screeninfo *var,
                                struct fb_info *info)
 {
        struct intelfb_par *par = info->par;
+       struct drm_device *dev = par->dev;
        struct drm_mode_set *modeset;
+       struct drm_crtc *crtc;
+       struct intel_crtc *intel_crtc;
        int ret = 0;
+       int i;
+
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               
+               for (i = 0; i < par->crtc_count; i++)
+                       if (crtc->base.id == par->crtc_ids[i])
+                               break;
+
+               if (i == par->crtc_count)
+                       continue;
+
+               intel_crtc = to_intel_crtc(crtc);
+               modeset = &intel_crtc->mode_set;
 
-       list_for_each_entry(modeset, &par->mode_set_list, head) {
                modeset->x = var->xoffset;
                modeset->y = var->yoffset;
 
                if (modeset->num_connectors) {
-                       ret = modeset->crtc->funcs->set_config(modeset);
+                       ret = crtc->funcs->set_config(modeset);
                  
                        if (!ret) {
                                info->var.xoffset = var->xoffset;
@@ -711,9 +749,8 @@ int intelfb_create(struct drm_device *dev, uint32_t fb_width, uint32_t fb_height
 
        fb->fbdev = info;
 
-       INIT_LIST_HEAD(&par->mode_set_list);
-
        par->intel_fb = intel_fb;
+       par->dev = dev;
 
        /* To allow resizeing without swapping buffers */
        printk("allocated %dx%d fb: 0x%08lx, bo %p\n", intel_fb->base.width,
@@ -724,48 +761,6 @@ int intelfb_create(struct drm_device *dev, uint32_t fb_width, uint32_t fb_height
 
 #define INTELFB_CONN_LIMIT 4
 
-static int intelfb_create_crtcmodesets(struct intel_framebuffer *intel_fb, int num_sets, int crtc_base)
-{
-       int i,j;
-       struct drm_device *dev = intel_fb->base.dev;
-       struct intelfb_par *par;
-       struct drm_mode_set *modeset;
-       struct drm_crtc *crtc;
-       struct fb_info *info;
-
-       info = intel_fb->base.fbdev;
-       par = info->par;
-
-       for (i = 0; i < num_sets; i++) {
-               modeset = kzalloc(sizeof(struct drm_mode_set) + (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL);
-               if (!modeset)
-                       goto fail;
-
-               /* attach a CRTC to the modeset */
-               j = 0;
-               list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-                       if (j == i + crtc_base) {
-                               modeset->crtc = crtc;
-                               break;
-                       }
-                       j++;
-               }
-               modeset->fb = &intel_fb->base;
-
-               modeset->connectors = (struct drm_connector **)(modeset + 1);
-               list_add_tail(&modeset->head, &par->mode_set_list);
-       }
-       return 0;
-
-fail:
-       list_for_each_entry(modeset, &par->mode_set_list, head) {
-               list_del(&modeset->head);
-               kfree(modeset);
-       }
-
-       return -ENOMEM;
-}
-
 static int intelfb_single_fb_probe(struct drm_device *dev)
 {
        struct drm_crtc *crtc;
@@ -795,7 +790,8 @@ static int intelfb_single_fb_probe(struct drm_device *dev)
                                        surface_width = crtc->desired_mode->hdisplay;
                                
                                if (crtc->desired_mode->vdisplay > surface_height)
-                               surface_height = crtc->desired_mode->vdisplay;
+                                       surface_height = crtc->desired_mode->vdisplay;
+
                        }
                crtc_count++;
                }
@@ -813,11 +809,6 @@ static int intelfb_single_fb_probe(struct drm_device *dev)
                ret = intelfb_create(dev, fb_width, fb_height, surface_width, surface_height, &intel_fb);
                if (ret)
                        return -EINVAL;
-
-               /* create a set per crtc connected to this fb */
-               ret = intelfb_create_crtcmodesets(intel_fb, dev->mode_config.num_crtc, 0);
-               if (ret)
-                       return ret;
                new_fb = 1;
        } else {
                struct drm_framebuffer *fb;
@@ -835,9 +826,12 @@ static int intelfb_single_fb_probe(struct drm_device *dev)
        info = intel_fb->base.fbdev;
        par = info->par;
 
+       crtc_count = 0;
        /* okay we need to setup new connector sets in the crtcs */
-       list_for_each_entry(modeset, &par->mode_set_list, head) {
-               
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+               modeset = &intel_crtc->mode_set;
+               modeset->fb = &intel_fb->base;
                conn_count = 0;
                list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                        if (connector->encoder)
@@ -852,10 +846,13 @@ static int intelfb_single_fb_probe(struct drm_device *dev)
                for (i = conn_count; i < INTELFB_CONN_LIMIT; i++)
                        modeset->connectors[i] = NULL;
 
+               par->crtc_ids[crtc_count++] = crtc->base.id;
+
                modeset->num_connectors = conn_count;
                if (modeset->mode != modeset->crtc->desired_mode)
                        modeset->mode = modeset->crtc->desired_mode;
        }
+       par->crtc_count = crtc_count;
 
        if (new_fb) {
                info->var.pixclock = -1;