diff options
Diffstat (limited to 'linux-core')
-rw-r--r-- | linux-core/drm_crtc.c | 87 | ||||
-rw-r--r-- | linux-core/drm_crtc.h | 2 | ||||
-rw-r--r-- | linux-core/drm_drv.c | 1 | ||||
-rw-r--r-- | linux-core/drm_fb.c | 10 | ||||
-rw-r--r-- | linux-core/intel_display.c | 21 |
5 files changed, 87 insertions, 34 deletions
diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index b349527d..2f140dbd 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -37,6 +37,7 @@ struct drm_framebuffer *drm_framebuffer_create(drm_device_t *dev) spin_lock(&dev->mode_config.config_lock); /* Limit to single framebuffer for now */ if (dev->mode_config.num_fb > 1) { + spin_unlock(&dev->mode_config.config_lock); DRM_ERROR("Attempt to add multiple framebuffers failed\n"); return NULL; } @@ -253,8 +254,7 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, /* Now, enable the clocks, plane, pipe, and outputs that we set up. */ crtc->funcs->commit(crtc); list_for_each_entry(output, &dev->mode_config.output_list, head) { - if (output->crtc == crtc) - { + if (output->crtc == crtc) { output->funcs->commit(output); #if 0 // TODO def RANDR_12_INTERFACE if (output->randr_output) @@ -542,6 +542,9 @@ bool drm_initial_config(drm_device_t *dev, struct drm_framebuffer *fb, list_for_each_entry(output, &dev->mode_config.output_list, head) { struct drm_display_mode *des_mode; + if (list_empty(&output->modes)) + continue; + /* Get the first preferred moded */ list_for_each_entry(des_mode, &output->modes, head) { if (des_mode->flags & DRM_MODE_TYPE_PREFERRED) @@ -579,7 +582,7 @@ void drm_mode_config_cleanup(drm_device_t *dev) { struct drm_output *output, *ot; struct drm_crtc *crtc, *ct; - + struct drm_crtc *fb, *fbt; list_for_each_entry_safe(output, ot, &dev->mode_config.output_list, head) { drm_output_destroy(output); } @@ -587,10 +590,15 @@ void drm_mode_config_cleanup(drm_device_t *dev) list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { drm_crtc_destroy(crtc); } + + list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { + drmfb_remove(dev, fb); + drm_framebuffer_destroy(fb); + } } 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 +611,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; @@ -617,8 +628,7 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, else new_crtc = output->crtc; - for (ro = 0; ro < crtc_info->count_outputs; ro++) - { + for (ro = 0; ro < crtc_info->count_outputs; ro++) { if (output_set[ro] == output) new_crtc = crtc; } @@ -629,6 +639,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 +908,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; @@ -904,23 +916,28 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp, return -EFAULT; crtc = idr_find(&dev->mode_config.crtc_idr, crtc_req.crtc_id); - if (!crtc || (crtc->id != crtc_req.crtc_id)) - { + if (!crtc || (crtc->id != crtc_req.crtc_id)) { DRM_DEBUG("Unknown CRTC ID %d\n", crtc_req.crtc_id); return -EINVAL; } 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)) - { - { - struct drm_output *output; - - list_for_each_entry(output, &dev->mode_config.output_list, head) { - list_for_each_entry(mode, &output->modes, head) { - drm_mode_debug_printmodeline(dev, mode); - } + if (!mode || (mode->mode_id != crtc_req.mode)) { + struct drm_output *output; + + list_for_each_entry(output, &dev->mode_config.output_list, head) { + list_for_each_entry(mode, &output->modes, head) { + drm_mode_debug_printmodeline(dev, mode); } } @@ -935,8 +952,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 +977,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; } @@ -1058,3 +1075,33 @@ int drm_mode_rmfb(struct inode *inode, struct file *filp, return 0; } +int drm_mode_getfb(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->head->dev; + struct drm_mode_fb_cmd __user *argp = (void __user *)arg; + struct drm_mode_fb_cmd r; + struct drm_framebuffer *fb; + + if (copy_from_user(&r, argp, sizeof(r))) + return -EFAULT; + + fb = idr_find(&dev->mode_config.crtc_idr, r.buffer_id); + if (!fb || (r.buffer_id != fb->id)) { + DRM_ERROR("invalid framebuffer id\n"); + return -EINVAL; + } + + r.height = fb->height; + r.width = fb->width; + r.depth = fb->depth; + r.bpp = fb->bits_per_pixel; + r.handle = fb->bo->base.hash.key; + r.pitch = fb->pitch; + + if (copy_to_user(argp, &r, sizeof(r))) + return -EFAULT; + + return 0; +} diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h index 54c508c5..c02dcedc 100644 --- a/linux-core/drm_crtc.h +++ b/linux-core/drm_crtc.h @@ -474,5 +474,7 @@ extern int drm_mode_addfb(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern int drm_mode_rmfb(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern int drm_mode_getfb(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); #endif /* __DRM_CRTC_H__ */ diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index b43af328..b7a7aded 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -129,6 +129,7 @@ static drm_ioctl_desc_t drm_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_MODE_SETCRTC)] = {drm_mode_setcrtc, DRM_MASTER|DRM_ROOT_ONLY}, [DRM_IOCTL_NR(DRM_IOCTL_MODE_ADDFB)] = {drm_mode_addfb, DRM_MASTER|DRM_ROOT_ONLY}, [DRM_IOCTL_NR(DRM_IOCTL_MODE_RMFB)] = {drm_mode_rmfb, DRM_MASTER|DRM_ROOT_ONLY}, + [DRM_IOCTL_NR(DRM_IOCTL_MODE_GETFB)] = {drm_mode_getfb, DRM_MASTER|DRM_ROOT_ONLY}, }; #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) diff --git a/linux-core/drm_fb.c b/linux-core/drm_fb.c index 1a0fb79c..a70e4d52 100644 --- a/linux-core/drm_fb.c +++ b/linux-core/drm_fb.c @@ -77,6 +77,15 @@ static int drmfb_setcolreg(unsigned regno, unsigned red, unsigned green, return 0; } +/* this will let fbcon do the mode init */ +static int drmfb_set_par(struct fb_info *info) +{ + struct drmfb_par *par = info->par; + struct drm_device *dev = par->dev; + + drm_set_desired_modes(dev); +} + static struct fb_ops drmfb_ops = { .owner = THIS_MODULE, // .fb_open = drmfb_open, @@ -84,6 +93,7 @@ static struct fb_ops drmfb_ops = { // .fb_write = drmfb_write, // .fb_release = drmfb_release, // .fb_ioctl = drmfb_ioctl, + .fb_set_par = drmfb_set_par, .fb_setcolreg = drmfb_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 396f4cfa..aed86231 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -412,8 +412,7 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) case DPMSModeSuspend: /* Enable the DPLL */ temp = I915_READ(dpll_reg); - if ((temp & DPLL_VCO_ENABLE) == 0) - { + if ((temp & DPLL_VCO_ENABLE) == 0) { I915_WRITE(dpll_reg, temp); I915_READ(dpll_reg); /* Wait for the clocks to stabilize. */ @@ -435,8 +434,7 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) /* Enable the plane */ temp = I915_READ(dspcntr_reg); - if ((temp & DISPLAY_PLANE_ENABLE) == 0) - { + if ((temp & DISPLAY_PLANE_ENABLE) == 0) { I915_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); /* Flush the plane changes */ I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); @@ -456,8 +454,7 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) /* Disable display plane */ temp = I915_READ(dspcntr_reg); - if ((temp & DISPLAY_PLANE_ENABLE) != 0) - { + if ((temp & DISPLAY_PLANE_ENABLE) != 0) { I915_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); /* Flush the plane changes */ I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); @@ -719,11 +716,9 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, dpll |= DPLLB_MODE_LVDS; else dpll |= DPLLB_MODE_DAC_SERIAL; - if (is_sdvo) - { + if (is_sdvo) { dpll |= DPLL_DVO_HIGH_SPEED; - if (IS_I945G(dev) || IS_I945GM(dev)) - { + if (IS_I945G(dev) || IS_I945GM(dev)) { int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; } @@ -760,8 +755,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, } } - if (is_tv) - { + if (is_tv) { /* XXX: just matching BIOS for now */ /* dpll |= PLL_REF_INPUT_TVCLKINBC; */ dpll |= 3; @@ -801,8 +795,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, dspcntr |= DISPPLANE_SEL_PIPE_B; pipeconf = I915_READ(pipeconf_reg); - if (pipe == 0 && !IS_I965G(dev)) - { + if (pipe == 0 && !IS_I965G(dev)) { /* Enable pixel doubling when the dot clock is > 90% of the (display) * core speed. * |