162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci#include <linux/module.h>
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <drm/drm_gem_ttm_helper.h>
662306a36Sopenharmony_ci#include <drm/ttm/ttm_placement.h>
762306a36Sopenharmony_ci#include <drm/ttm/ttm_tt.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci/**
1062306a36Sopenharmony_ci * DOC: overview
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * This library provides helper functions for gem objects backed by
1362306a36Sopenharmony_ci * ttm.
1462306a36Sopenharmony_ci */
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci/**
1762306a36Sopenharmony_ci * drm_gem_ttm_print_info() - Print &ttm_buffer_object info for debugfs
1862306a36Sopenharmony_ci * @p: DRM printer
1962306a36Sopenharmony_ci * @indent: Tab indentation level
2062306a36Sopenharmony_ci * @gem: GEM object
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci * This function can be used as &drm_gem_object_funcs.print_info
2362306a36Sopenharmony_ci * callback.
2462306a36Sopenharmony_ci */
2562306a36Sopenharmony_civoid drm_gem_ttm_print_info(struct drm_printer *p, unsigned int indent,
2662306a36Sopenharmony_ci			    const struct drm_gem_object *gem)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	static const char * const plname[] = {
2962306a36Sopenharmony_ci		[ TTM_PL_SYSTEM ] = "system",
3062306a36Sopenharmony_ci		[ TTM_PL_TT     ] = "tt",
3162306a36Sopenharmony_ci		[ TTM_PL_VRAM   ] = "vram",
3262306a36Sopenharmony_ci		[ TTM_PL_PRIV   ] = "priv",
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci		[ 16 ]            = "cached",
3562306a36Sopenharmony_ci		[ 17 ]            = "uncached",
3662306a36Sopenharmony_ci		[ 18 ]            = "wc",
3762306a36Sopenharmony_ci		[ 19 ]            = "contig",
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci		[ 21 ]            = "pinned", /* NO_EVICT */
4062306a36Sopenharmony_ci		[ 22 ]            = "topdown",
4162306a36Sopenharmony_ci	};
4262306a36Sopenharmony_ci	const struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gem);
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	drm_printf_indent(p, indent, "placement=");
4562306a36Sopenharmony_ci	drm_print_bits(p, bo->resource->placement, plname, ARRAY_SIZE(plname));
4662306a36Sopenharmony_ci	drm_printf(p, "\n");
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	if (bo->resource->bus.is_iomem)
4962306a36Sopenharmony_ci		drm_printf_indent(p, indent, "bus.offset=%lx\n",
5062306a36Sopenharmony_ci				  (unsigned long)bo->resource->bus.offset);
5162306a36Sopenharmony_ci}
5262306a36Sopenharmony_ciEXPORT_SYMBOL(drm_gem_ttm_print_info);
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci/**
5562306a36Sopenharmony_ci * drm_gem_ttm_vmap() - vmap &ttm_buffer_object
5662306a36Sopenharmony_ci * @gem: GEM object.
5762306a36Sopenharmony_ci * @map: [out] returns the dma-buf mapping.
5862306a36Sopenharmony_ci *
5962306a36Sopenharmony_ci * Maps a GEM object with ttm_bo_vmap(). This function can be used as
6062306a36Sopenharmony_ci * &drm_gem_object_funcs.vmap callback.
6162306a36Sopenharmony_ci *
6262306a36Sopenharmony_ci * Returns:
6362306a36Sopenharmony_ci * 0 on success, or a negative errno code otherwise.
6462306a36Sopenharmony_ci */
6562306a36Sopenharmony_ciint drm_gem_ttm_vmap(struct drm_gem_object *gem,
6662306a36Sopenharmony_ci		     struct iosys_map *map)
6762306a36Sopenharmony_ci{
6862306a36Sopenharmony_ci	struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gem);
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	return ttm_bo_vmap(bo, map);
7162306a36Sopenharmony_ci}
7262306a36Sopenharmony_ciEXPORT_SYMBOL(drm_gem_ttm_vmap);
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci/**
7562306a36Sopenharmony_ci * drm_gem_ttm_vunmap() - vunmap &ttm_buffer_object
7662306a36Sopenharmony_ci * @gem: GEM object.
7762306a36Sopenharmony_ci * @map: dma-buf mapping.
7862306a36Sopenharmony_ci *
7962306a36Sopenharmony_ci * Unmaps a GEM object with ttm_bo_vunmap(). This function can be used as
8062306a36Sopenharmony_ci * &drm_gem_object_funcs.vmap callback.
8162306a36Sopenharmony_ci */
8262306a36Sopenharmony_civoid drm_gem_ttm_vunmap(struct drm_gem_object *gem,
8362306a36Sopenharmony_ci			struct iosys_map *map)
8462306a36Sopenharmony_ci{
8562306a36Sopenharmony_ci	struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gem);
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	ttm_bo_vunmap(bo, map);
8862306a36Sopenharmony_ci}
8962306a36Sopenharmony_ciEXPORT_SYMBOL(drm_gem_ttm_vunmap);
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci/**
9262306a36Sopenharmony_ci * drm_gem_ttm_mmap() - mmap &ttm_buffer_object
9362306a36Sopenharmony_ci * @gem: GEM object.
9462306a36Sopenharmony_ci * @vma: vm area.
9562306a36Sopenharmony_ci *
9662306a36Sopenharmony_ci * This function can be used as &drm_gem_object_funcs.mmap
9762306a36Sopenharmony_ci * callback.
9862306a36Sopenharmony_ci */
9962306a36Sopenharmony_ciint drm_gem_ttm_mmap(struct drm_gem_object *gem,
10062306a36Sopenharmony_ci		     struct vm_area_struct *vma)
10162306a36Sopenharmony_ci{
10262306a36Sopenharmony_ci	struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gem);
10362306a36Sopenharmony_ci	int ret;
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	ret = ttm_bo_mmap_obj(vma, bo);
10662306a36Sopenharmony_ci	if (ret < 0)
10762306a36Sopenharmony_ci		return ret;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	/*
11062306a36Sopenharmony_ci	 * ttm has its own object refcounting, so drop gem reference
11162306a36Sopenharmony_ci	 * to avoid double accounting counting.
11262306a36Sopenharmony_ci	 */
11362306a36Sopenharmony_ci	drm_gem_object_put(gem);
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	return 0;
11662306a36Sopenharmony_ci}
11762306a36Sopenharmony_ciEXPORT_SYMBOL(drm_gem_ttm_mmap);
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci/**
12062306a36Sopenharmony_ci * drm_gem_ttm_dumb_map_offset() - Implements struct &drm_driver.dumb_map_offset
12162306a36Sopenharmony_ci * @file:	DRM file pointer.
12262306a36Sopenharmony_ci * @dev:	DRM device.
12362306a36Sopenharmony_ci * @handle:	GEM handle
12462306a36Sopenharmony_ci * @offset:	Returns the mapping's memory offset on success
12562306a36Sopenharmony_ci *
12662306a36Sopenharmony_ci * Provides an implementation of struct &drm_driver.dumb_map_offset for
12762306a36Sopenharmony_ci * TTM-based GEM drivers. TTM allocates the offset internally and
12862306a36Sopenharmony_ci * drm_gem_ttm_dumb_map_offset() returns it for dumb-buffer implementations.
12962306a36Sopenharmony_ci *
13062306a36Sopenharmony_ci * See struct &drm_driver.dumb_map_offset.
13162306a36Sopenharmony_ci *
13262306a36Sopenharmony_ci * Returns:
13362306a36Sopenharmony_ci * 0 on success, or a negative errno code otherwise.
13462306a36Sopenharmony_ci */
13562306a36Sopenharmony_ciint drm_gem_ttm_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
13662306a36Sopenharmony_ci				uint32_t handle, uint64_t *offset)
13762306a36Sopenharmony_ci{
13862306a36Sopenharmony_ci	struct drm_gem_object *gem;
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	gem = drm_gem_object_lookup(file, handle);
14162306a36Sopenharmony_ci	if (!gem)
14262306a36Sopenharmony_ci		return -ENOENT;
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	*offset = drm_vma_node_offset_addr(&gem->vma_node);
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	drm_gem_object_put(gem);
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	return 0;
14962306a36Sopenharmony_ci}
15062306a36Sopenharmony_ciEXPORT_SYMBOL(drm_gem_ttm_dumb_map_offset);
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ciMODULE_DESCRIPTION("DRM gem ttm helpers");
15362306a36Sopenharmony_ciMODULE_LICENSE("GPL");
154