summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-core/intel_display.c6
-rw-r--r--linux-core/intel_drv.h4
-rw-r--r--linux-core/intel_fb.c119
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;