intelfb: add multi fb paths

main
Dave Airlie 2008-06-06 15:21:22 +10:00
parent e6a3a1fdad
commit be501f00a3
1 changed files with 91 additions and 4 deletions

View File

@ -759,6 +759,94 @@ int intelfb_create(struct drm_device *dev, uint32_t fb_width, uint32_t fb_height
return 0;
}
static int intelfb_multi_fb_probe_crtc(struct drm_device *dev, struct drm_crtc *crtc)
{
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_framebuffer *intel_fb;
struct drm_framebuffer *fb;
struct drm_connector *connector;
struct fb_info *info;
struct intelfb_par *par;
struct drm_mode_set *modeset;
unsigned int width, height;
int new_fb = 0;
int ret, i, conn_count;
if (!drm_helper_crtc_in_use(crtc))
return 0;
if (!crtc->desired_mode)
return 0;
width = crtc->desired_mode->hdisplay;
height = crtc->desired_mode->vdisplay;
/* is there an fb bound to this crtc already */
if (!intel_crtc->mode_set.fb) {
ret = intelfb_create(dev, width, height, width, height, &intel_fb);
if (ret)
return -EINVAL;
new_fb = 1;
} else {
fb = intel_crtc->mode_set.fb;
intel_fb = to_intel_framebuffer(fb);
if ((intel_fb->base.width < width) || (intel_fb->base.height < height))
return -EINVAL;
}
info = intel_fb->base.fbdev;
par = info->par;
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)
if (connector->encoder->crtc == modeset->crtc) {
modeset->connectors[conn_count] = connector;
conn_count++;
if (conn_count > INTELFB_CONN_LIMIT)
BUG();
}
}
for (i = conn_count; i < INTELFB_CONN_LIMIT; i++)
modeset->connectors[i] = NULL;
par->crtc_ids[0] = crtc->base.id;
modeset->num_connectors = conn_count;
if (modeset->mode != modeset->crtc->desired_mode)
modeset->mode = modeset->crtc->desired_mode;
par->crtc_count = 1;
if (new_fb) {
info->var.pixclock = -1;
if (register_framebuffer(info) < 0)
return -EINVAL;
} else
intelfb_set_par(info);
printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
info->fix.id);
return 0;
}
static int intelfb_multi_fb_probe(struct drm_device *dev)
{
struct drm_crtc *crtc;
int ret = 0;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
ret = intelfb_multi_fb_probe_crtc(dev, crtc);
if (ret)
return ret;
}
return ret;
}
static int intelfb_single_fb_probe(struct drm_device *dev)
{
struct drm_crtc *crtc;
@ -891,12 +979,11 @@ int intelfb_probe(struct drm_device *dev)
/* mode a first */
/* search for an fb */
if (i915_fbpercrtc == 1) {
ret = -EINVAL;
goto fail;
ret = intelfb_multi_fb_probe(dev);
} else {
ret = intelfb_single_fb_probe(dev);
}
ret = intelfb_single_fb_probe(dev);
fail:
/* TODO */
return ret;