diff options
author | Dave Airlie <airlied@redhat.com> | 2022-04-12 17:39:45 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2022-04-12 17:44:27 +1000 |
commit | b85ffe47c4ec172214a38b7e7087c60582c488f0 (patch) | |
tree | 128168c955a62a870f7da7cfda94e9299a076486 /drivers/gpu/drm/omapdrm/omap_gem.c | |
parent | ce522ba9ef7e2d9fb22a39eb3371c0c64e2a433e (diff) | |
parent | c8d4c18bfbc4ab467188dbe45cc8155759f49d9e (diff) |
Merge tag 'drm-misc-next-2022-04-07' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for 5.19:
UAPI Changes:
Cross-subsystem Changes:
Core Changes:
- atomic: Add atomic_print_state to private objects
- edid: Constify the EDID parsing API, rework of the API
- dma-buf: Add dma_resv_replace_fences, dma_resv_get_singleton, make
dma_resv_excl_fence private
- format: Support monochrome formats
- fbdev: fixes for cfb_imageblit and sys_imageblit, pagelist
corruption fix
- selftests: several small fixes
- ttm: Rework bulk move handling
Driver Changes:
- Switch all relevant drivers to drm_mode_copy or drm_mode_duplicate
- bridge: conversions to devm_drm_of_get_bridge and panel_bridge,
autosuspend for analogix_dp, audio support for it66121, DSI to DPI
support for tc358767, PLL fixes and I2C support for icn6211
- bridge_connector: Enable HPD if supported
- etnaviv: fencing improvements
- gma500: GEM and GTT improvements, connector handling fixes
- komeda: switch to plane reset helper
- mediatek: MIPI DSI improvements
- omapdrm: GEM improvements
- panel: DT bindings fixes for st7735r, few fixes for ssd130x, new
panels: ltk035c5444t, B133UAN01, NV3052C
- qxl: Allow to run on arm64
- sysfb: Kconfig rework, support for VESA graphic mode selection
- vc4: Add a tracepoint for CL submissions, HDMI YUV output,
HDMI and clock improvements
- virtio: Remove restriction of non-zero blob_flags,
- vmwgfx: support for CursorMob and CursorBypass 4, various
improvements and small fixes
[airlied: fixup conflict with newvision panel callbacks]
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Maxime Ripard <maxime@cerno.tech>
Link: https://patchwork.freedesktop.org/patch/msgid/20220407085940.pnflvjojs4qw4b77@houat
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_gem.c')
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_gem.c | 198 |
1 files changed, 113 insertions, 85 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index b0fa17409b66..cf571796fd26 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -38,7 +38,7 @@ struct omap_gem_object { /** roll applied when mapping to DMM */ u32 roll; - /** protects dma_addr_cnt, block, pages, dma_addrs and vaddr */ + /** protects pin_cnt, block, pages, dma_addrs and vaddr */ struct mutex lock; /** @@ -50,24 +50,24 @@ struct omap_gem_object { * - buffers imported from dmabuf (with the OMAP_BO_MEM_DMABUF flag set) * if they are physically contiguous (when sgt->orig_nents == 1) * - * - buffers mapped through the TILER when dma_addr_cnt is not zero, in - * which case the DMA address points to the TILER aperture + * - buffers mapped through the TILER when pin_cnt is not zero, in which + * case the DMA address points to the TILER aperture * * Physically contiguous buffers have their DMA address equal to the * physical address as we don't remap those buffers through the TILER. * * Buffers mapped to the TILER have their DMA address pointing to the - * TILER aperture. As TILER mappings are refcounted (through - * dma_addr_cnt) the DMA address must be accessed through omap_gem_pin() - * to ensure that the mapping won't disappear unexpectedly. References - * must be released with omap_gem_unpin(). + * TILER aperture. As TILER mappings are refcounted (through pin_cnt) + * the DMA address must be accessed through omap_gem_pin() to ensure + * that the mapping won't disappear unexpectedly. References must be + * released with omap_gem_unpin(). */ dma_addr_t dma_addr; /** - * # of users of dma_addr + * # of users */ - refcount_t dma_addr_cnt; + refcount_t pin_cnt; /** * If the buffer has been imported from a dmabuf the OMAP_DB_DMABUF flag @@ -750,6 +750,46 @@ void omap_gem_dma_sync_buffer(struct drm_gem_object *obj, } } +static int omap_gem_pin_tiler(struct drm_gem_object *obj) +{ + struct omap_gem_object *omap_obj = to_omap_bo(obj); + u32 npages = obj->size >> PAGE_SHIFT; + enum tiler_fmt fmt = gem2fmt(omap_obj->flags); + struct tiler_block *block; + int ret; + + BUG_ON(omap_obj->block); + + if (omap_obj->flags & OMAP_BO_TILED_MASK) { + block = tiler_reserve_2d(fmt, omap_obj->width, omap_obj->height, + PAGE_SIZE); + } else { + block = tiler_reserve_1d(obj->size); + } + + if (IS_ERR(block)) { + ret = PTR_ERR(block); + dev_err(obj->dev->dev, "could not remap: %d (%d)\n", ret, fmt); + goto fail; + } + + /* TODO: enable async refill.. */ + ret = tiler_pin(block, omap_obj->pages, npages, omap_obj->roll, true); + if (ret) { + tiler_release(block); + dev_err(obj->dev->dev, "could not pin: %d\n", ret); + goto fail; + } + + omap_obj->dma_addr = tiler_ssptr(block); + omap_obj->block = block; + + DBG("got dma address: %pad", &omap_obj->dma_addr); + +fail: + return ret; +} + /** * omap_gem_pin() - Pin a GEM object in memory * @obj: the GEM object @@ -772,63 +812,30 @@ int omap_gem_pin(struct drm_gem_object *obj, dma_addr_t *dma_addr) mutex_lock(&omap_obj->lock); - if (!omap_gem_is_contiguous(omap_obj) && priv->has_dmm) { - if (refcount_read(&omap_obj->dma_addr_cnt) == 0) { - u32 npages = obj->size >> PAGE_SHIFT; - enum tiler_fmt fmt = gem2fmt(omap_obj->flags); - struct tiler_block *block; - - BUG_ON(omap_obj->block); + if (!omap_gem_is_contiguous(omap_obj)) { + if (refcount_read(&omap_obj->pin_cnt) == 0) { - refcount_set(&omap_obj->dma_addr_cnt, 1); + refcount_set(&omap_obj->pin_cnt, 1); ret = omap_gem_attach_pages(obj); if (ret) goto fail; - if (omap_obj->flags & OMAP_BO_TILED_MASK) { - block = tiler_reserve_2d(fmt, - omap_obj->width, - omap_obj->height, PAGE_SIZE); - } else { - block = tiler_reserve_1d(obj->size); - } - - if (IS_ERR(block)) { - ret = PTR_ERR(block); - dev_err(obj->dev->dev, - "could not remap: %d (%d)\n", ret, fmt); - goto fail; - } - - /* TODO: enable async refill.. */ - ret = tiler_pin(block, omap_obj->pages, npages, - omap_obj->roll, true); - if (ret) { - tiler_release(block); - dev_err(obj->dev->dev, - "could not pin: %d\n", ret); - goto fail; + if (omap_obj->flags & OMAP_BO_SCANOUT) { + if (priv->has_dmm) { + ret = omap_gem_pin_tiler(obj); + if (ret) + goto fail; + } } - - omap_obj->dma_addr = tiler_ssptr(block); - omap_obj->block = block; - - DBG("got dma address: %pad", &omap_obj->dma_addr); } else { - refcount_inc(&omap_obj->dma_addr_cnt); + refcount_inc(&omap_obj->pin_cnt); } - - if (dma_addr) - *dma_addr = omap_obj->dma_addr; - } else if (omap_gem_is_contiguous(omap_obj)) { - if (dma_addr) - *dma_addr = omap_obj->dma_addr; - } else { - ret = -EINVAL; - goto fail; } + if (dma_addr) + *dma_addr = omap_obj->dma_addr; + fail: mutex_unlock(&omap_obj->lock); @@ -847,27 +854,31 @@ static void omap_gem_unpin_locked(struct drm_gem_object *obj) struct omap_gem_object *omap_obj = to_omap_bo(obj); int ret; - if (omap_gem_is_contiguous(omap_obj) || !priv->has_dmm) + if (omap_gem_is_contiguous(omap_obj)) return; - if (refcount_dec_and_test(&omap_obj->dma_addr_cnt)) { + if (refcount_dec_and_test(&omap_obj->pin_cnt)) { if (omap_obj->sgt) { sg_free_table(omap_obj->sgt); kfree(omap_obj->sgt); omap_obj->sgt = NULL; } - ret = tiler_unpin(omap_obj->block); - if (ret) { - dev_err(obj->dev->dev, - "could not unpin pages: %d\n", ret); - } - ret = tiler_release(omap_obj->block); - if (ret) { - dev_err(obj->dev->dev, - "could not release unmap: %d\n", ret); + if (!(omap_obj->flags & OMAP_BO_SCANOUT)) + return; + if (priv->has_dmm) { + ret = tiler_unpin(omap_obj->block); + if (ret) { + dev_err(obj->dev->dev, + "could not unpin pages: %d\n", ret); + } + ret = tiler_release(omap_obj->block); + if (ret) { + dev_err(obj->dev->dev, + "could not release unmap: %d\n", ret); + } + omap_obj->dma_addr = 0; + omap_obj->block = NULL; } - omap_obj->dma_addr = 0; - omap_obj->block = NULL; } } @@ -900,7 +911,7 @@ int omap_gem_rotated_dma_addr(struct drm_gem_object *obj, u32 orient, mutex_lock(&omap_obj->lock); - if ((refcount_read(&omap_obj->dma_addr_cnt) > 0) && omap_obj->block && + if ((refcount_read(&omap_obj->pin_cnt) > 0) && omap_obj->block && (omap_obj->flags & OMAP_BO_TILED_MASK)) { *dma_addr = tiler_tsptr(omap_obj->block, orient, x, y); ret = 0; @@ -968,7 +979,8 @@ int omap_gem_put_pages(struct drm_gem_object *obj) return 0; } -struct sg_table *omap_gem_get_sg(struct drm_gem_object *obj) +struct sg_table *omap_gem_get_sg(struct drm_gem_object *obj, + enum dma_data_direction dir) { struct omap_gem_object *omap_obj = to_omap_bo(obj); dma_addr_t addr; @@ -993,28 +1005,44 @@ struct sg_table *omap_gem_get_sg(struct drm_gem_object *obj) goto err_unpin; } - if (omap_obj->flags & OMAP_BO_TILED_MASK) { - enum tiler_fmt fmt = gem2fmt(omap_obj->flags); + if (addr) { + if (omap_obj->flags & OMAP_BO_TILED_MASK) { + enum tiler_fmt fmt = gem2fmt(omap_obj->flags); - len = omap_obj->width << (int)fmt; - count = omap_obj->height; - stride = tiler_stride(fmt, 0); + len = omap_obj->width << (int)fmt; + count = omap_obj->height; + stride = tiler_stride(fmt, 0); + } else { + len = obj->size; + count = 1; + stride = 0; + } } else { - len = obj->size; - count = 1; - stride = 0; + count = obj->size >> PAGE_SHIFT; } ret = sg_alloc_table(sgt, count, GFP_KERNEL); if (ret) goto err_free; - for_each_sg(sgt->sgl, sg, count, i) { - sg_set_page(sg, phys_to_page(addr), len, offset_in_page(addr)); - sg_dma_address(sg) = addr; - sg_dma_len(sg) = len; + /* this must be after omap_gem_pin() to ensure we have pages attached */ + omap_gem_dma_sync_buffer(obj, dir); - addr += stride; + if (addr) { + for_each_sg(sgt->sgl, sg, count, i) { + sg_set_page(sg, phys_to_page(addr), len, + offset_in_page(addr)); + sg_dma_address(sg) = addr; + sg_dma_len(sg) = len; + + addr += stride; + } + } else { + for_each_sg(sgt->sgl, sg, count, i) { + sg_set_page(sg, omap_obj->pages[i], PAGE_SIZE, 0); + sg_dma_address(sg) = omap_obj->dma_addrs[i]; + sg_dma_len(sg) = PAGE_SIZE; + } } omap_obj->sgt = sgt; @@ -1124,7 +1152,7 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m) seq_printf(m, "%08x: %2d (%2d) %08llx %pad (%2d) %p %4d", omap_obj->flags, obj->name, kref_read(&obj->refcount), off, &omap_obj->dma_addr, - refcount_read(&omap_obj->dma_addr_cnt), + refcount_read(&omap_obj->pin_cnt), omap_obj->vaddr, omap_obj->roll); if (omap_obj->flags & OMAP_BO_TILED_MASK) { @@ -1187,7 +1215,7 @@ static void omap_gem_free_object(struct drm_gem_object *obj) mutex_lock(&omap_obj->lock); /* The object should not be pinned. */ - WARN_ON(refcount_read(&omap_obj->dma_addr_cnt) > 0); + WARN_ON(refcount_read(&omap_obj->pin_cnt) > 0); if (omap_obj->pages) { if (omap_obj->flags & OMAP_BO_MEM_DMABUF) |