allow framebuffer changes on the crtc setup
authorDave Airlie <airlied@linux.ie>
Wed, 11 Apr 2007 22:54:31 +0000 (08:54 +1000)
committerDave Airlie <airlied@linux.ie>
Wed, 11 Apr 2007 22:54:31 +0000 (08:54 +1000)
libdrm/xf86drmMode.c
libdrm/xf86drmMode.h
linux-core/drm_crtc.c

index 6070ec6..cb53467 100644 (file)
@@ -276,7 +276,7 @@ drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
        r->mode            = crtc.mode;
 //     r->width           = crtc.width;
 //     r->height          = crtc.height;
-       r->bufferId        = crtc.fb_id;
+       r->buffer_id        = crtc.fb_id;
        r->gamma_size      = crtc.gamma_size;
        r->count_outputs   = crtc.count_outputs;
        r->count_possibles = crtc.count_possibles;
index 6a566c4..c87a95d 100644 (file)
@@ -80,7 +80,7 @@ typedef struct drm_mode_fb_cmd drmModeFrameBuffer, *drmModeFrameBufferPtr;
 
 typedef struct _drmModeCrtc {
 
-       unsigned int bufferId; /**< Buffer currently connected to */
+       unsigned int buffer_id; /**< FB id to connect to 0 = disconnect*/
 
        uint32_t x, y; /**< Position on the frameuffer */
        uint32_t width, height;
index d1f3c07..21d7012 100644 (file)
@@ -590,7 +590,7 @@ void drm_mode_config_cleanup(drm_device_t *dev)
 }
 EXPORT_SYMBOL(drm_mode_config_cleanup);
 
-int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, struct drm_display_mode *new_mode, struct drm_output **output_set)
+int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, struct drm_display_mode *new_mode, struct drm_output **output_set, struct drm_framebuffer *fb)
 {
        drm_device_t *dev = crtc->dev;
        struct drm_crtc **save_crtcs, *new_crtc;
@@ -603,6 +603,9 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info,
        if (!save_crtcs)
                return -ENOMEM;
 
+       if (crtc->fb != fb)
+               changed = true;
+
        if (crtc_info->x != crtc->x || crtc_info->y != crtc->y)
                changed = true;
 
@@ -629,6 +632,7 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info,
        }
 
        if (changed) {
+               crtc->fb = fb;
                crtc->enabled = (new_mode != NULL);
                if (new_mode != NULL) {
                        DRM_DEBUG("attempting to set mode from userspace\n");
@@ -897,6 +901,7 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp,
        struct drm_crtc *crtc;
        struct drm_output **output_set = NULL, *output;
        struct drm_display_mode *mode;
+       struct drm_framebuffer *fb = NULL;
        int retcode = 0;
        int i;
 
@@ -911,6 +916,15 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp,
        }
 
        if (crtc_req.mode) {
+
+               /* if we have a mode we need a framebuffer */
+               if (crtc_req.fb_id) {
+                       fb = idr_find(&dev->mode_config.crtc_idr, crtc_req.fb_id);
+                       if (!fb || (fb->id != crtc_req.fb_id)) {
+                               DRM_DEBUG("Unknown FB ID%d\n", crtc_req.fb_id);
+                               return -EINVAL;
+                       }
+               }
                mode = idr_find(&dev->mode_config.crtc_idr, crtc_req.mode);
                if (!mode || (mode->mode_id != crtc_req.mode))
                {
@@ -935,8 +949,8 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp,
                return -EINVAL;
        }
 
-       if (crtc_req.count_outputs > 0 && !mode) {
-               DRM_DEBUG("Count outputs is %d but no mode set\n", crtc_req.count_outputs);
+       if (crtc_req.count_outputs > 0 && !mode && !fb) {
+               DRM_DEBUG("Count outputs is %d but no mode or fb set\n", crtc_req.count_outputs);
                return -EINVAL;
        }
 
@@ -960,7 +974,7 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp,
                }
        }
                
-       retcode = drm_crtc_set_config(crtc, &crtc_req, mode, output_set);
+       retcode = drm_crtc_set_config(crtc, &crtc_req, mode, output_set, fb);
        return retcode;
 }