diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-02 19:40:34 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-02 19:40:34 -0700 |
commit | 20a2078ce7705a6e0722ef5184336eb8657a58d8 (patch) | |
tree | 5b927c96516380aa0ecd68d8a609f7cd72120ad5 /drivers/gpu/drm/mgag200/mgag200_fb.c | |
parent | 0279b3c0ada1d78882f24acf94ac4595bd657a89 (diff) | |
parent | 307b9c022720f9de90d58e51743e01e9a42aec59 (diff) |
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie:
"This is the main drm pull request for 3.10.
Wierd bits:
- OMAP drm changes required OMAP dss changes, in drivers/video, so I
took them in here.
- one more fbcon fix for font handover
- VT switch avoidance in pm code
- scatterlist helpers for gpu drivers - have acks from akpm
Highlights:
- qxl kms driver - driver for the spice qxl virtual GPU
Nouveau:
- fermi/kepler VRAM compression
- GK110/nvf0 modesetting support.
Tegra:
- host1x core merged with 2D engine support
i915:
- vt switchless resume
- more valleyview support
- vblank fixes
- modesetting pipe config rework
radeon:
- UVD engine support
- SI chip tiling support
- GPU registers initialisation from golden values.
exynos:
- device tree changes
- fimc block support
Otherwise:
- bunches of fixes all over the place."
* 'drm-next' of git://people.freedesktop.org/~airlied/linux: (513 commits)
qxl: update to new idr interfaces.
drm/nouveau: fix build with nv50->nvc0
drm/radeon: fix handling of v6 power tables
drm/radeon: clarify family checks in pm table parsing
drm/radeon: consolidate UVD clock programming
drm/radeon: fix UPLL_REF_DIV_MASK definition
radeon: add bo tracking debugfs
drm/radeon: add new richland pci ids
drm/radeon: add some new SI PCI ids
drm/radeon: fix scratch reg handling for UVD fence
drm/radeon: allocate SA bo in the requested domain
drm/radeon: fix possible segfault when parsing pm tables
drm/radeon: fix endian bugs in atom_allocate_fb_scratch()
OMAPDSS: TFP410: return EPROBE_DEFER if the i2c adapter not found
OMAPDSS: VENC: Add error handling for venc_probe_pdata
OMAPDSS: HDMI: Add error handling for hdmi_probe_pdata
OMAPDSS: RFBI: Add error handling for rfbi_probe_pdata
OMAPDSS: DSI: Add error handling for dsi_probe_pdata
OMAPDSS: SDI: Add error handling for sdi_probe_pdata
OMAPDSS: DPI: Add error handling for dpi_probe_pdata
...
Diffstat (limited to 'drivers/gpu/drm/mgag200/mgag200_fb.c')
-rw-r--r-- | drivers/gpu/drm/mgag200/mgag200_fb.c | 55 |
1 files changed, 43 insertions, 12 deletions
diff --git a/drivers/gpu/drm/mgag200/mgag200_fb.c b/drivers/gpu/drm/mgag200/mgag200_fb.c index d2253f63948..5da824ce9ba 100644 --- a/drivers/gpu/drm/mgag200/mgag200_fb.c +++ b/drivers/gpu/drm/mgag200/mgag200_fb.c @@ -29,16 +29,52 @@ static void mga_dirty_update(struct mga_fbdev *mfbdev, int bpp = (mfbdev->mfb.base.bits_per_pixel + 7)/8; int ret; bool unmap = false; + bool store_for_later = false; + int x2, y2; + unsigned long flags; obj = mfbdev->mfb.obj; bo = gem_to_mga_bo(obj); + /* + * try and reserve the BO, if we fail with busy + * then the BO is being moved and we should + * store up the damage until later. + */ ret = mgag200_bo_reserve(bo, true); if (ret) { - DRM_ERROR("failed to reserve fb bo\n"); + if (ret != -EBUSY) + return; + + store_for_later = true; + } + + x2 = x + width - 1; + y2 = y + height - 1; + spin_lock_irqsave(&mfbdev->dirty_lock, flags); + + if (mfbdev->y1 < y) + y = mfbdev->y1; + if (mfbdev->y2 > y2) + y2 = mfbdev->y2; + if (mfbdev->x1 < x) + x = mfbdev->x1; + if (mfbdev->x2 > x2) + x2 = mfbdev->x2; + + if (store_for_later) { + mfbdev->x1 = x; + mfbdev->x2 = x2; + mfbdev->y1 = y; + mfbdev->y2 = y2; + spin_unlock_irqrestore(&mfbdev->dirty_lock, flags); return; } + mfbdev->x1 = mfbdev->y1 = INT_MAX; + mfbdev->x2 = mfbdev->y2 = 0; + spin_unlock_irqrestore(&mfbdev->dirty_lock, flags); + if (!bo->kmap.virtual) { ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap); if (ret) { @@ -48,10 +84,10 @@ static void mga_dirty_update(struct mga_fbdev *mfbdev, } unmap = true; } - for (i = y; i < y + height; i++) { + for (i = y; i <= y2; i++) { /* assume equal stride for now */ src_offset = dst_offset = i * mfbdev->mfb.base.pitches[0] + (x * bpp); - memcpy_toio(bo->kmap.virtual + src_offset, mfbdev->sysram + src_offset, width * bpp); + memcpy_toio(bo->kmap.virtual + src_offset, mfbdev->sysram + src_offset, (x2 - x + 1) * bpp); } if (unmap) @@ -105,12 +141,9 @@ static int mgag200fb_create_object(struct mga_fbdev *afbdev, struct drm_gem_object **gobj_p) { struct drm_device *dev = afbdev->helper.dev; - u32 bpp, depth; u32 size; struct drm_gem_object *gobj; - int ret = 0; - drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); size = mode_cmd->pitches[0] * mode_cmd->height; ret = mgag200_gem_create(dev, size, true, &gobj); @@ -249,19 +282,19 @@ int mgag200_fbdev_init(struct mga_device *mdev) struct mga_fbdev *mfbdev; int ret; - mfbdev = kzalloc(sizeof(struct mga_fbdev), GFP_KERNEL); + mfbdev = devm_kzalloc(mdev->dev->dev, sizeof(struct mga_fbdev), GFP_KERNEL); if (!mfbdev) return -ENOMEM; mdev->mfbdev = mfbdev; mfbdev->helper.funcs = &mga_fb_helper_funcs; + spin_lock_init(&mfbdev->dirty_lock); ret = drm_fb_helper_init(mdev->dev, &mfbdev->helper, mdev->num_crtc, MGAG200FB_CONN_LIMIT); - if (ret) { - kfree(mfbdev); + if (ret) return ret; - } + drm_fb_helper_single_add_all_connectors(&mfbdev->helper); /* disable all the possible outputs/crtcs before entering KMS mode */ @@ -278,6 +311,4 @@ void mgag200_fbdev_fini(struct mga_device *mdev) return; mga_fbdev_destroy(mdev->dev, mdev->mfbdev); - kfree(mdev->mfbdev); - mdev->mfbdev = NULL; } |