From: Jesse Barnes on 4 Jan 2010 12:30 Can you send this one over to Dave Airlie <airlied(a)linux.ie>? At KS he indicated he'd be happy to just apply it, since other drivers will need it too (along with the driver specific code of course). Jesse On Wed, 23 Dec 2009 15:43:00 -0600 Jason Wessel <jason.wessel(a)windriver.com> wrote: > From: Jesse Barnes <jbarnes(a)virtuousgeek.org> > > --- > drivers/gpu/drm/drm_fb_helper.c | 83 > ++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_display.c > | 93 ++++++++++++++++++++++++++++++++++ > include/drm/drm_crtc_helper.h | 2 + > include/drm/drm_fb_helper.h | 4 ++ 4 files changed, 182 > insertions(+), 0 deletions(-) > > diff --git a/drivers/gpu/drm/drm_fb_helper.c > b/drivers/gpu/drm/drm_fb_helper.c index 1b49fa0..80aab3c 100644 > --- a/drivers/gpu/drm/drm_fb_helper.c > +++ b/drivers/gpu/drm/drm_fb_helper.c > @@ -29,6 +29,7 @@ > */ > #include <linux/sysrq.h> > #include <linux/fb.h> > +#include <linux/kgdb.h> > #include "drmP.h" > #include "drm_crtc.h" > #include "drm_fb_helper.h" > @@ -233,6 +234,84 @@ int drm_fb_helper_parse_command_line(struct > drm_device *dev) return 0; > } > > +#define to_fb_helper(ops) (container_of((ops), struct drm_fb_helper, > kdb_ops)) + > +static int drm_fb_kdb_enter(struct dbg_kms_console_ops *ops) > +{ > + struct drm_fb_helper *helper = to_fb_helper(ops); > + struct drm_crtc_helper_funcs *funcs; > + int i; > + > + if (atomic_read(&kgdb_active)) > + goto out; /* already in KDB, don't reset mode */ > + > + if (list_empty(&kernel_fb_helper_list)) > + return false; > + > + list_for_each_entry(helper, &kernel_fb_helper_list, > kernel_fb_list) { > + for (i = 0; i < helper->crtc_count; i++) { > + struct drm_mode_set *mode_set = > + &helper->crtc_info[i].mode_set; > + > + if (!mode_set->crtc->enabled) > + continue; > + > + funcs = > mode_set->crtc->helper_private; > + funcs->mode_set_base_atomic(mode_set->crtc, > + mode_set->fb, > + mode_set->x, > + mode_set->y); > + > + } > + } > + > +out: > + return 0; > +} > + > +/* Find the real fb for a given fb helper CRTC */ > +static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc > *crtc) +{ > + struct drm_device *dev = crtc->dev; > + struct drm_crtc *c; > + > + list_for_each_entry(c, &dev->mode_config.crtc_list, head) { > + if (crtc->base.id == c->base.id) > + return c->fb; > + } > + > + return NULL; > +} > + > +static int drm_fb_kdb_exit(struct dbg_kms_console_ops *ops) > +{ > + struct drm_fb_helper *helper = to_fb_helper(ops); > + struct drm_crtc *crtc; > + struct drm_crtc_helper_funcs *funcs; > + struct drm_framebuffer *fb; > + int i; > + > + for (i = 0; i < helper->crtc_count; i++) { > + struct drm_mode_set *mode_set = > &helper->crtc_info[i].mode_set; > + crtc = mode_set->crtc; > + funcs = crtc->helper_private; > + fb = drm_mode_config_fb(crtc); > + > + if (!crtc->enabled) > + continue; > + > + if (!fb) { > + DRM_ERROR("no fb to restore??\n"); > + continue; > + } > + > + funcs->mode_set_base_atomic(mode_set->crtc, fb, > crtc->x, > + crtc->y); > + } > + > + return 0; > +} > + > bool drm_fb_helper_force_kernel_mode(void) > { > int i = 0; > @@ -924,6 +1003,9 @@ int drm_fb_helper_single_fb_probe(struct > drm_device *dev, /* Switch back to kernel console on panic */ > /* multi card linked list maybe */ > if (list_empty(&kernel_fb_helper_list)) { > + fb_helper->kdb_ops.activate_console = > drm_fb_kdb_enter; > + fb_helper->kdb_ops.restore_console = drm_fb_kdb_exit; > + dbg_kms_console_ops_register(&fb_helper->kdb_ops); > printk(KERN_INFO "registered panic notifier\n"); > atomic_notifier_chain_register(&panic_notifier_list, > &paniced); > @@ -938,6 +1020,7 @@ void drm_fb_helper_free(struct drm_fb_helper > *helper) { > list_del(&helper->kernel_fb_list); > if (list_empty(&kernel_fb_helper_list)) { > + dbg_kms_console_ops_unregister(&helper->kdb_ops); > printk(KERN_INFO "unregistered panic notifier\n"); > atomic_notifier_chain_unregister(&panic_notifier_list, > &paniced); > diff --git a/drivers/gpu/drm/i915/intel_display.c > b/drivers/gpu/drm/i915/intel_display.c index 52cd9b0..e134a81 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -1234,6 +1234,98 @@ intel_pin_and_fence_fb_obj(struct drm_device > *dev, struct drm_gem_object *obj) return 0; > } > > +/* Assume fb object is pinned & idle & fenced and just update base > pointers */ +static int > +intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct > drm_framebuffer *fb, > + int x, int y) > +{ > + struct drm_device *dev = crtc->dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); > + struct intel_framebuffer *intel_fb; > + struct drm_i915_gem_object *obj_priv; > + struct drm_gem_object *obj; > + int plane = intel_crtc->plane; > + unsigned long Start, Offset; > + int dspbase = (plane == 0 ? DSPAADDR : DSPBADDR); > + int dspsurf = (plane == 0 ? DSPASURF : DSPBSURF); > + int dspstride = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE; > + int dsptileoff = (plane == 0 ? DSPATILEOFF : DSPBTILEOFF); > + int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; > + u32 dspcntr; > + > + switch (plane) { > + case 0: > + case 1: > + break; > + default: > + DRM_ERROR("Can't update plane %d in SAREA\n", plane); > + return -EINVAL; > + } > + > + intel_fb = to_intel_framebuffer(fb); > + obj = intel_fb->obj; > + obj_priv = obj->driver_private; > + > + dspcntr = I915_READ(dspcntr_reg); > + /* Mask out pixel format bits in case we change it */ > + dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; > + switch (fb->bits_per_pixel) { > + case 8: > + dspcntr |= DISPPLANE_8BPP; > + break; > + case 16: > + if (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 -EINVAL; > + } > + if (IS_I965G(dev)) { > + if (obj_priv->tiling_mode != I915_TILING_NONE) > + dspcntr |= DISPPLANE_TILED; > + else > + dspcntr &= ~DISPPLANE_TILED; > + } > + > + if (IS_IRONLAKE(dev)) > + /* must disable */ > + dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; > + > + I915_WRITE(dspcntr_reg, dspcntr); > + > + Start = obj_priv->gtt_offset; > + Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8); > + > + DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, > x, y); > + I915_WRITE(dspstride, fb->pitch); > + if (IS_I965G(dev)) { > + I915_WRITE(dspbase, Offset); > + I915_READ(dspbase); > + I915_WRITE(dspsurf, Start); > + I915_READ(dspsurf); > + I915_WRITE(dsptileoff, (y << 16) | x); > + } else { > + I915_WRITE(dspbase, Start + Offset); > + I915_READ(dspbase); > + } > + > + if ((IS_I965G(dev) || plane == 0)) > + intel_update_fbc(crtc, &crtc->mode); > + > + intel_wait_for_vblank(dev); > + intel_increase_pllclock(crtc, true); > + > + return 0; > +} > + > static int > intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, > struct drm_framebuffer *old_fb) > @@ -4243,6 +4335,7 @@ static const struct drm_crtc_helper_funcs > intel_helper_funcs = { .mode_fixup = intel_crtc_mode_fixup, > .mode_set = intel_crtc_mode_set, > .mode_set_base = intel_pipe_set_base, > + .mode_set_base_atomic = intel_pipe_set_base_atomic, > .prepare = intel_crtc_prepare, > .commit = intel_crtc_commit, > .load_lut = intel_crtc_load_lut, > diff --git a/include/drm/drm_crtc_helper.h > b/include/drm/drm_crtc_helper.h index b29e201..4c12319 100644 > --- a/include/drm/drm_crtc_helper.h > +++ b/include/drm/drm_crtc_helper.h > @@ -61,6 +61,8 @@ struct drm_crtc_helper_funcs { > /* Move the crtc on the current fb to the given position > *optional* */ int (*mode_set_base)(struct drm_crtc *crtc, int x, int > y, struct drm_framebuffer *old_fb); > + int (*mode_set_base_atomic)(struct drm_crtc *crtc, > + struct drm_framebuffer *fb, int > x, int y); > /* reload the current crtc LUT */ > void (*load_lut)(struct drm_crtc *crtc); > diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h > index 58c892a..c4f87a5 100644 > --- a/include/drm/drm_fb_helper.h > +++ b/include/drm/drm_fb_helper.h > @@ -30,6 +30,8 @@ > #ifndef DRM_FB_HELPER_H > #define DRM_FB_HELPER_H > > +#include <linux/kgdb.h> > + > struct drm_fb_helper_crtc { > uint32_t crtc_id; > struct drm_mode_set mode_set; > @@ -63,8 +65,10 @@ struct drm_fb_helper_connector { > > struct drm_fb_helper { > struct drm_framebuffer *fb; > + struct drm_framebuffer *saved_fb; > struct drm_device *dev; > struct drm_display_mode *mode; > + struct dbg_kms_console_ops kdb_ops; > int crtc_count; > struct drm_fb_helper_crtc *crtc_info; > struct drm_fb_helper_funcs *funcs; -- Jesse Barnes, Intel Open Source Technology Center -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo(a)vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
|
Pages: 1 Prev: Add DMI quirk for Intel DP55KG mainboard Next: [PATCH 0/3] Regulator updates for 2.6.34 |