diff options
-rw-r--r-- | linux-core/intel_display.c | 6 | ||||
-rw-r--r-- | linux-core/intel_drv.h | 4 | ||||
-rw-r--r-- | linux-core/intel_fb.c | 119 |
3 files changed, 67 insertions, 62 deletions
diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index e2d2a5fb..0081b5be 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -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) { diff --git a/linux-core/intel_drv.h b/linux-core/intel_drv.h index 25e2a652..1008e271 100644 --- a/linux-core/intel_drv.h +++ b/linux-core/intel_drv.h @@ -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) diff --git a/linux-core/intel_fb.c b/linux-core/intel_fb.c index 5ec5bb8f..71f71a0d 100644 --- a/linux-core/intel_fb.c +++ b/linux-core/intel_fb.c @@ -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; |