diff options
-rw-r--r-- | linux-core/drmP.h | 3 | ||||
-rw-r--r-- | linux-core/drm_crtc.c | 35 | ||||
-rw-r--r-- | linux-core/drm_crtc.h | 2 | ||||
-rw-r--r-- | linux-core/intel_display.c | 54 | ||||
-rw-r--r-- | linux-core/intel_fb.c | 118 |
5 files changed, 105 insertions, 107 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 0f42d5b6..181b3a97 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -173,8 +173,6 @@ struct drm_file; #include "drm_compat.h" -#include "drm_crtc.h" - /***********************************************************************/ /** \name Macros to make printk easier */ /*@{*/ @@ -610,6 +608,7 @@ struct drm_ati_pcigart_info { }; #include "drm_objects.h" +#include "drm_crtc.h" /* per-master structure */ struct drm_master { diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 73ab10ec..36d9fc56 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -418,7 +418,6 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, saved_mode; int saved_x, saved_y; bool didLock = false; - bool ret = false; struct drm_output *output; adjusted_mode = drm_mode_duplicate(dev, mode); @@ -442,8 +441,13 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, crtc->x = x; crtc->y = y; - /* XXX short-circuit changes to base location only */ - + if (drm_mode_equal(&saved_mode, &crtc->mode)) { + if (saved_x != crtc->x || saved_y != crtc->y) { + crtc->funcs->mode_set_base(crtc, crtc->x, crtc->y); + goto done; + } + } + /* Pass our mode to the outputs and the CRTC to give them a chance to * adjust it according to limitations or output properties, and also * a chance to reject the mode entirely. @@ -507,22 +511,15 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, /* XXX free adjustedmode */ drm_mode_destroy(dev, adjusted_mode); - ret = TRUE; /* TODO */ // if (scrn->pScreen) // drm_crtc_set_screen_sub_pixel_order(dev); done: - if (!ret) { - crtc->x = saved_x; - crtc->y = saved_y; - crtc->mode = saved_mode; - } - if (didLock) crtc->funcs->unlock (crtc); - return ret; + return true; } EXPORT_SYMBOL(drm_crtc_set_mode); @@ -1599,13 +1596,13 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_crtc *crtc_req = data; - struct drm_crtc *crtc; + struct drm_crtc *crtc, *crtcfb; struct drm_output **output_set = NULL, *output; struct drm_framebuffer *fb = NULL; struct drm_display_mode *mode = NULL; + uint32_t __user *set_outputs_ptr; int ret = 0; int i; - uint32_t __user *set_outputs_ptr; mutex_lock(&dev->mode_config.mutex); crtc = idr_find(&dev->mode_config.crtc_idr, crtc_req->crtc_id); @@ -1616,8 +1613,16 @@ int drm_mode_setcrtc(struct drm_device *dev, } if (crtc_req->mode_valid) { - /* if we have a mode we need a framebuffer */ - if (crtc_req->fb_id) { + /* If we have a mode we need a framebuffer. */ + /* If we pass -1, set the mode with the currently bound fb */ + if (crtc_req->fb_id == -1) { + list_for_each_entry(crtcfb, &dev->mode_config.crtc_list, head) { + if (crtcfb == crtc) { + DRM_INFO("Using current fb for setmode\n"); + fb = crtc->fb; + } + } + } else { 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); diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h index d733d8ca..bbeab603 100644 --- a/linux-core/drm_crtc.h +++ b/linux-core/drm_crtc.h @@ -244,7 +244,7 @@ struct drm_framebuffer { struct drm_buffer_object *bo; void *fbdev; u32 pseudo_palette[17]; - void *virtual_base; + struct drm_bo_kmap_obj kmap; struct list_head filp_head; }; diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 6a9d9808..003739d7 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -369,10 +369,42 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) unsigned long Start, Offset; int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); + int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; + int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; + u32 dspcntr; + + /* no fb bound */ + if (!crtc->fb) { + DRM_INFO("No FB bound\n"); + return; + } Start = crtc->fb->bo->offset; Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); + I915_WRITE(dspstride, crtc->fb->pitch); + + dspcntr = I915_READ(dspcntr_reg); + switch (crtc->fb->bits_per_pixel) { + case 8: + dspcntr |= DISPPLANE_8BPP; + break; + case 16: + if (crtc->fb->depth == 15) + dspcntr |= DISPPLANE_15_16BPP; + else + dspcntr |= DISPPLANE_16BPP; + break; + case 24: + case 32: + dspcntr |= DISPPLANE_32BPP_NO_ALPHA; + break; + default: + DRM_ERROR("Unknown color depth\n"); + return; + } + I915_WRITE(dspcntr_reg, dspcntr); + DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y); if (IS_I965G(dev)) { I915_WRITE(dspbase, Offset); @@ -691,7 +723,6 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; - int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; int refclk; @@ -804,26 +835,6 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, /* Set up the display plane register */ dspcntr = DISPPLANE_GAMMA_ENABLE; - switch (crtc->fb->bits_per_pixel) { - case 8: - dspcntr |= DISPPLANE_8BPP; - break; - case 16: - if (crtc->fb->depth == 15) - dspcntr |= DISPPLANE_15_16BPP; - else - dspcntr |= DISPPLANE_16BPP; - break; - case 24: - case 32: - dspcntr |= DISPPLANE_32BPP_NO_ALPHA; - break; - default: - DRM_ERROR("Unknown color depth\n"); - return; - } - - if (pipe == 0) dspcntr |= DISPPLANE_SEL_PIPE_A; else @@ -925,7 +936,6 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, ((adjusted_mode->crtc_vblank_end - 1) << 16)); I915_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16)); - I915_WRITE(dspstride_reg, crtc->fb->pitch); /* pipesrc and dspsize control the size that is scaled from, which should * always be the user's requested size. */ diff --git a/linux-core/intel_fb.c b/linux-core/intel_fb.c index 56403998..e33494c6 100644 --- a/linux-core/intel_fb.c +++ b/linux-core/intel_fb.c @@ -48,6 +48,7 @@ struct intelfb_par { struct drm_device *dev; struct drm_crtc *crtc; struct drm_display_mode *fb_mode; + struct drm_framebuffer *fb; }; /* static int @@ -66,7 +67,7 @@ static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green, struct fb_info *info) { struct intelfb_par *par = info->par; - struct drm_framebuffer *fb = par->crtc->fb; + struct drm_framebuffer *fb = par->fb; struct drm_crtc *crtc = par->crtc; if (regno > 255) @@ -107,7 +108,7 @@ static int intelfb_check_var(struct fb_var_screeninfo *var, { struct intelfb_par *par = info->par; /*struct drm_device *dev = par->dev;*/ - struct drm_framebuffer *fb = par->crtc->fb; + struct drm_framebuffer *fb = par->fb; /*struct drm_output *output;*/ int depth/*, found = 0*/; @@ -216,41 +217,15 @@ static int intelfb_check_var(struct fb_var_screeninfo *var, return 0; } -bool i915_drmfb_mode_equal(struct drm_display_mode *mode1, struct drm_display_mode *mode2, unsigned int pixclock) -{ - - if (mode1->hdisplay == mode2->hdisplay && - mode1->hsync_start == mode2->hsync_start && - mode1->hsync_end == mode2->hsync_end && - mode1->htotal == mode2->htotal && - mode1->hskew == mode2->hskew && - mode1->vdisplay == mode2->vdisplay && - mode1->vsync_start == mode2->vsync_start && - mode1->vsync_end == mode2->vsync_end && - mode1->vtotal == mode2->vtotal && - mode1->vscan == mode2->vscan && - mode1->flags == mode2->flags) - { - if (mode1->clock == mode2->clock) - return true; - - if (KHZ2PICOS(mode2->clock) == pixclock) - return true; - return false; - } - - return false; -} - /* this will let fbcon do the mode init */ /* FIXME: take mode config lock? */ static int intelfb_set_par(struct fb_info *info) { struct intelfb_par *par = info->par; - struct drm_framebuffer *fb = par->crtc->fb; + struct drm_framebuffer *fb = par->fb; struct drm_device *dev = par->dev; struct drm_display_mode *drm_mode, *search_mode; - struct drm_output *output; + struct drm_output *output = NULL; struct fb_var_screeninfo *var = &info->var; int found = 0; @@ -295,15 +270,23 @@ static int intelfb_set_par(struct fb_info *info) drm_mode_set_name(drm_mode); drm_mode_set_crtcinfo(drm_mode, CRTC_INTERLACE_HALVE_V); + found = 0; list_for_each_entry(output, &dev->mode_config.output_list, head) { - if (output->crtc == par->crtc) + if (output->crtc == par->crtc){ + found = 1; break; + } } + /* no output bound, bail */ + if (!found) + return -EINVAL; + + found = 0; drm_mode_debug_printmodeline(dev, drm_mode); list_for_each_entry(search_mode, &output->modes, head) { drm_mode_debug_printmodeline(dev, search_mode); - if (i915_drmfb_mode_equal(drm_mode, search_mode, var->pixclock)) { + if (drm_mode_equal(drm_mode, search_mode)) { drm_mode_destroy(dev, drm_mode); drm_mode = search_mode; found = 1; @@ -311,8 +294,12 @@ static int intelfb_set_par(struct fb_info *info) } } + /* If we didn't find a matching mode that exists on our output, + * create a new attachment for the incoming user specified mode + */ if (!found) { if (par->fb_mode) { + /* this also destroys the mode */ drm_mode_detachmode_crtc(dev, par->fb_mode); } @@ -322,21 +309,13 @@ static int intelfb_set_par(struct fb_info *info) drm_mode_attachmode_crtc(dev, par->crtc, par->fb_mode); } - if (par->crtc->enabled) { - if (!drm_mode_equal(&par->crtc->mode, drm_mode)) { - if (!drm_crtc_set_mode(par->crtc, drm_mode, var->xoffset, var->yoffset)) - return -EINVAL; - } else if (par->crtc->x != var->xoffset || par->crtc->y != var->yoffset) { - if (!par->crtc->funcs->mode_set_base) { - if (!drm_crtc_set_mode(par->crtc, drm_mode, var->xoffset, var->yoffset)) - return -EINVAL; - } else { - par->crtc->funcs->mode_set_base(par->crtc, var->xoffset, var->yoffset); - par->crtc->x = var->xoffset; - par->crtc->y = var->yoffset; - } - } - } + /* re-attach fb */ + if (!par->crtc->fb) + par->crtc->fb = par->fb; + + if (!drm_crtc_set_mode(par->crtc, drm_mode, var->xoffset, var->yoffset)) + return -EINVAL; + return 0; } @@ -493,17 +472,14 @@ static int intelfb_pan_display(struct fb_var_screeninfo *var, DRM_DEBUG("\n"); - if (!crtc->funcs->mode_set_base) { - DRM_ERROR("panning not supported\n"); - return -EFAULT; - } - /* TODO add check size and pos*/ - crtc->funcs->mode_set_base(crtc, var->xoffset, var->yoffset); + /* re-attach fb */ + if (!crtc->fb) + crtc->fb = par->fb; + + drm_crtc_set_mode(crtc, &crtc->mode, var->xoffset, var->yoffset); - par->crtc->x = var->xoffset; - par->crtc->y = var->yoffset; info->var.xoffset = var->xoffset; info->var.yoffset = var->yoffset; @@ -535,7 +511,7 @@ static struct fb_ops intelfb_ops = { */ int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc) { - struct fb_info *info; + struct fb_info *info; struct drm_framebuffer *fb; struct drm_display_mode *mode = crtc->desired_mode; @@ -559,7 +535,7 @@ int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc) info->var.vsync_len = mode->vsync_end - mode->vsync_start; info->var.upper_margin = mode->vtotal - mode->vsync_end; info->var.pixclock = 10000000 / mode->htotal * 1000 / mode->vtotal * 100; - /* avoid overflow */ + /* avoid overflow */ info->var.pixclock = info->var.pixclock * 1000 / mode->vrefresh; return 0; @@ -596,7 +572,7 @@ int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc) fb->bits_per_pixel = 32; fb->pitch = fb->width * ((fb->bits_per_pixel + 1) / 8); fb->depth = 24; - ret = drm_buffer_object_create(dev, fb->width * fb->height * 4, + ret = drm_buffer_object_create(dev, fb->pitch * fb->height * 4, drm_bo_type_kernel, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | @@ -623,6 +599,7 @@ int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc) par->dev = dev; par->crtc = crtc; + par->fb = fb; info->fbops = &intelfb_ops; @@ -635,19 +612,26 @@ int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc) info->fix.ywrapstep = 0; info->fix.accel = FB_ACCEL_I830; info->fix.type_aux = 0; - info->fix.mmio_start = 0; - info->fix.mmio_len = 0; + + if (IS_I9XX(dev)) { + info->fix.mmio_start = pci_resource_start(dev->pdev, 0); + info->fix.mmio_len = pci_resource_len(dev->pdev, 0); + } else { + info->fix.mmio_start = pci_resource_start(dev->pdev, 1); + info->fix.mmio_len = pci_resource_len(dev->pdev, 1); + } + info->fix.line_length = fb->pitch; info->fix.smem_start = fb->bo->offset + dev->mode_config.fb_base; info->fix.smem_len = info->fix.line_length * fb->height; info->flags = FBINFO_DEFAULT; - ret = drm_mem_reg_ioremap(dev, &fb->bo->mem, &fb->virtual_base); - if (ret) - DRM_ERROR("error mapping fb: %d\n", ret); - - info->screen_base = fb->virtual_base; + ret = drm_bo_kmap(fb->bo, 0, fb->bo->num_pages, &fb->kmap); + if (ret) + DRM_ERROR("error mapping fb: %d\n", ret); + + info->screen_base = fb->kmap.virtual; info->screen_size = info->fix.smem_len; /* FIXME */ info->pseudo_palette = fb->pseudo_palette; info->var.xres_virtual = fb->width; @@ -757,10 +741,10 @@ int intelfb_remove(struct drm_device *dev, struct drm_crtc *crtc) if (info) { unregister_framebuffer(info); - framebuffer_release(info); - drm_mem_reg_iounmap(dev, &fb->bo->mem, fb->virtual_base); + drm_bo_kunmap(&fb->kmap); drm_bo_usage_deref_unlocked(&fb->bo); drm_framebuffer_destroy(fb); + framebuffer_release(info); } return 0; } |