xref: /third_party/libdrm/nouveau/abi16.c (revision d722e3fb)
1d722e3fbSopenharmony_ci/*
2d722e3fbSopenharmony_ci * Copyright 2012 Red Hat Inc.
3d722e3fbSopenharmony_ci *
4d722e3fbSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5d722e3fbSopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6d722e3fbSopenharmony_ci * to deal in the Software without restriction, including without limitation
7d722e3fbSopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8d722e3fbSopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9d722e3fbSopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10d722e3fbSopenharmony_ci *
11d722e3fbSopenharmony_ci * The above copyright notice and this permission notice shall be included in
12d722e3fbSopenharmony_ci * all copies or substantial portions of the Software.
13d722e3fbSopenharmony_ci *
14d722e3fbSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15d722e3fbSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16d722e3fbSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17d722e3fbSopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18d722e3fbSopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19d722e3fbSopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20d722e3fbSopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
21d722e3fbSopenharmony_ci *
22d722e3fbSopenharmony_ci * Authors: Ben Skeggs
23d722e3fbSopenharmony_ci */
24d722e3fbSopenharmony_ci
25d722e3fbSopenharmony_ci#include <stdlib.h>
26d722e3fbSopenharmony_ci#include <stdint.h>
27d722e3fbSopenharmony_ci#include <stddef.h>
28d722e3fbSopenharmony_ci#include <errno.h>
29d722e3fbSopenharmony_ci
30d722e3fbSopenharmony_ci#include "private.h"
31d722e3fbSopenharmony_ci
32d722e3fbSopenharmony_ci#include "nvif/class.h"
33d722e3fbSopenharmony_ci
34d722e3fbSopenharmony_cistatic int
35d722e3fbSopenharmony_ciabi16_chan_nv04(struct nouveau_object *obj)
36d722e3fbSopenharmony_ci{
37d722e3fbSopenharmony_ci	struct nouveau_drm *drm = nouveau_drm(obj);
38d722e3fbSopenharmony_ci	struct nv04_fifo *nv04 = obj->data;
39d722e3fbSopenharmony_ci	struct drm_nouveau_channel_alloc req = {
40d722e3fbSopenharmony_ci		.fb_ctxdma_handle = nv04->vram,
41d722e3fbSopenharmony_ci		.tt_ctxdma_handle = nv04->gart
42d722e3fbSopenharmony_ci	};
43d722e3fbSopenharmony_ci	int ret;
44d722e3fbSopenharmony_ci
45d722e3fbSopenharmony_ci	ret = drmCommandWriteRead(drm->fd, DRM_NOUVEAU_CHANNEL_ALLOC,
46d722e3fbSopenharmony_ci				  &req, sizeof(req));
47d722e3fbSopenharmony_ci	if (ret)
48d722e3fbSopenharmony_ci		return ret;
49d722e3fbSopenharmony_ci
50d722e3fbSopenharmony_ci	nv04->base.channel = req.channel;
51d722e3fbSopenharmony_ci	nv04->base.pushbuf = req.pushbuf_domains;
52d722e3fbSopenharmony_ci	nv04->notify = req.notifier_handle;
53d722e3fbSopenharmony_ci	nv04->base.object->handle = req.channel;
54d722e3fbSopenharmony_ci	nv04->base.object->length = sizeof(*nv04);
55d722e3fbSopenharmony_ci	return 0;
56d722e3fbSopenharmony_ci}
57d722e3fbSopenharmony_ci
58d722e3fbSopenharmony_cistatic int
59d722e3fbSopenharmony_ciabi16_chan_nvc0(struct nouveau_object *obj)
60d722e3fbSopenharmony_ci{
61d722e3fbSopenharmony_ci	struct nouveau_drm *drm = nouveau_drm(obj);
62d722e3fbSopenharmony_ci	struct drm_nouveau_channel_alloc req = {};
63d722e3fbSopenharmony_ci	struct nvc0_fifo *nvc0 = obj->data;
64d722e3fbSopenharmony_ci	int ret;
65d722e3fbSopenharmony_ci
66d722e3fbSopenharmony_ci	ret = drmCommandWriteRead(drm->fd, DRM_NOUVEAU_CHANNEL_ALLOC,
67d722e3fbSopenharmony_ci				  &req, sizeof(req));
68d722e3fbSopenharmony_ci	if (ret)
69d722e3fbSopenharmony_ci		return ret;
70d722e3fbSopenharmony_ci
71d722e3fbSopenharmony_ci	nvc0->base.channel = req.channel;
72d722e3fbSopenharmony_ci	nvc0->base.pushbuf = req.pushbuf_domains;
73d722e3fbSopenharmony_ci	nvc0->notify = req.notifier_handle;
74d722e3fbSopenharmony_ci	nvc0->base.object->handle = req.channel;
75d722e3fbSopenharmony_ci	nvc0->base.object->length = sizeof(*nvc0);
76d722e3fbSopenharmony_ci	return 0;
77d722e3fbSopenharmony_ci}
78d722e3fbSopenharmony_ci
79d722e3fbSopenharmony_cistatic int
80d722e3fbSopenharmony_ciabi16_chan_nve0(struct nouveau_object *obj)
81d722e3fbSopenharmony_ci{
82d722e3fbSopenharmony_ci	struct nouveau_drm *drm = nouveau_drm(obj);
83d722e3fbSopenharmony_ci	struct drm_nouveau_channel_alloc req = {};
84d722e3fbSopenharmony_ci	struct nve0_fifo *nve0 = obj->data;
85d722e3fbSopenharmony_ci	int ret;
86d722e3fbSopenharmony_ci
87d722e3fbSopenharmony_ci	if (obj->length > offsetof(struct nve0_fifo, engine)) {
88d722e3fbSopenharmony_ci		req.fb_ctxdma_handle = 0xffffffff;
89d722e3fbSopenharmony_ci		req.tt_ctxdma_handle = nve0->engine;
90d722e3fbSopenharmony_ci	}
91d722e3fbSopenharmony_ci
92d722e3fbSopenharmony_ci	ret = drmCommandWriteRead(drm->fd, DRM_NOUVEAU_CHANNEL_ALLOC,
93d722e3fbSopenharmony_ci				  &req, sizeof(req));
94d722e3fbSopenharmony_ci	if (ret)
95d722e3fbSopenharmony_ci		return ret;
96d722e3fbSopenharmony_ci
97d722e3fbSopenharmony_ci	nve0->base.channel = req.channel;
98d722e3fbSopenharmony_ci	nve0->base.pushbuf = req.pushbuf_domains;
99d722e3fbSopenharmony_ci	nve0->notify = req.notifier_handle;
100d722e3fbSopenharmony_ci	nve0->base.object->handle = req.channel;
101d722e3fbSopenharmony_ci	nve0->base.object->length = sizeof(*nve0);
102d722e3fbSopenharmony_ci	return 0;
103d722e3fbSopenharmony_ci}
104d722e3fbSopenharmony_ci
105d722e3fbSopenharmony_cistatic int
106d722e3fbSopenharmony_ciabi16_engobj(struct nouveau_object *obj)
107d722e3fbSopenharmony_ci{
108d722e3fbSopenharmony_ci	struct nouveau_drm *drm = nouveau_drm(obj);
109d722e3fbSopenharmony_ci	struct drm_nouveau_grobj_alloc req = {
110d722e3fbSopenharmony_ci		.channel = obj->parent->handle,
111d722e3fbSopenharmony_ci		.handle = obj->handle,
112d722e3fbSopenharmony_ci		.class = obj->oclass,
113d722e3fbSopenharmony_ci	};
114d722e3fbSopenharmony_ci	int ret;
115d722e3fbSopenharmony_ci
116d722e3fbSopenharmony_ci	/* Older kernel versions did not have the concept of nouveau-
117d722e3fbSopenharmony_ci	 * specific classes and abused some NVIDIA-assigned ones for
118d722e3fbSopenharmony_ci	 * a SW class.  The ABI16 layer has compatibility in place to
119d722e3fbSopenharmony_ci	 * translate these older identifiers to the newer ones.
120d722e3fbSopenharmony_ci	 *
121d722e3fbSopenharmony_ci	 * Clients that have been updated to use NVIF are required to
122d722e3fbSopenharmony_ci	 * use the newer class identifiers, which means that they'll
123d722e3fbSopenharmony_ci	 * break if running on an older kernel.
124d722e3fbSopenharmony_ci	 *
125d722e3fbSopenharmony_ci	 * To handle this case, when using ABI16, we translate to the
126d722e3fbSopenharmony_ci	 * older values which work on any kernel.
127d722e3fbSopenharmony_ci	 */
128d722e3fbSopenharmony_ci	switch (req.class) {
129d722e3fbSopenharmony_ci	case NVIF_CLASS_SW_NV04 : req.class = 0x006e; break;
130d722e3fbSopenharmony_ci	case NVIF_CLASS_SW_NV10 : req.class = 0x016e; break;
131d722e3fbSopenharmony_ci	case NVIF_CLASS_SW_NV50 : req.class = 0x506e; break;
132d722e3fbSopenharmony_ci	case NVIF_CLASS_SW_GF100: req.class = 0x906e; break;
133d722e3fbSopenharmony_ci	default:
134d722e3fbSopenharmony_ci		break;
135d722e3fbSopenharmony_ci	}
136d722e3fbSopenharmony_ci
137d722e3fbSopenharmony_ci	ret = drmCommandWrite(drm->fd, DRM_NOUVEAU_GROBJ_ALLOC,
138d722e3fbSopenharmony_ci			      &req, sizeof(req));
139d722e3fbSopenharmony_ci	if (ret)
140d722e3fbSopenharmony_ci		return ret;
141d722e3fbSopenharmony_ci
142d722e3fbSopenharmony_ci	obj->length = sizeof(struct nouveau_object *);
143d722e3fbSopenharmony_ci	return 0;
144d722e3fbSopenharmony_ci}
145d722e3fbSopenharmony_ci
146d722e3fbSopenharmony_cistatic int
147d722e3fbSopenharmony_ciabi16_ntfy(struct nouveau_object *obj)
148d722e3fbSopenharmony_ci{
149d722e3fbSopenharmony_ci	struct nouveau_drm *drm = nouveau_drm(obj);
150d722e3fbSopenharmony_ci	struct nv04_notify *ntfy = obj->data;
151d722e3fbSopenharmony_ci	struct drm_nouveau_notifierobj_alloc req = {
152d722e3fbSopenharmony_ci		.channel = obj->parent->handle,
153d722e3fbSopenharmony_ci		.handle = ntfy->object->handle,
154d722e3fbSopenharmony_ci		.size = ntfy->length,
155d722e3fbSopenharmony_ci	};
156d722e3fbSopenharmony_ci	int ret;
157d722e3fbSopenharmony_ci
158d722e3fbSopenharmony_ci	ret = drmCommandWriteRead(drm->fd, DRM_NOUVEAU_NOTIFIEROBJ_ALLOC,
159d722e3fbSopenharmony_ci				  &req, sizeof(req));
160d722e3fbSopenharmony_ci	if (ret)
161d722e3fbSopenharmony_ci		return ret;
162d722e3fbSopenharmony_ci
163d722e3fbSopenharmony_ci	ntfy->offset = req.offset;
164d722e3fbSopenharmony_ci	ntfy->object->length = sizeof(*ntfy);
165d722e3fbSopenharmony_ci	return 0;
166d722e3fbSopenharmony_ci}
167d722e3fbSopenharmony_ci
168d722e3fbSopenharmony_cidrm_private int
169d722e3fbSopenharmony_ciabi16_sclass(struct nouveau_object *obj, struct nouveau_sclass **psclass)
170d722e3fbSopenharmony_ci{
171d722e3fbSopenharmony_ci	struct nouveau_sclass *sclass;
172d722e3fbSopenharmony_ci	struct nouveau_device *dev;
173d722e3fbSopenharmony_ci
174d722e3fbSopenharmony_ci	if (!(sclass = calloc(8, sizeof(*sclass))))
175d722e3fbSopenharmony_ci		return -ENOMEM;
176d722e3fbSopenharmony_ci	*psclass = sclass;
177d722e3fbSopenharmony_ci
178d722e3fbSopenharmony_ci	switch (obj->oclass) {
179d722e3fbSopenharmony_ci	case NOUVEAU_FIFO_CHANNEL_CLASS:
180d722e3fbSopenharmony_ci		/* Older kernel versions were exposing the wrong video engine
181d722e3fbSopenharmony_ci		 * classes on certain G98:GF100 boards.  This has since been
182d722e3fbSopenharmony_ci		 * corrected, but ABI16 has compatibility in place to avoid
183d722e3fbSopenharmony_ci		 * breaking older userspace.
184d722e3fbSopenharmony_ci		 *
185d722e3fbSopenharmony_ci		 * Clients that have been updated to use NVIF are required to
186d722e3fbSopenharmony_ci		 * use the correct classes, which means that they'll break if
187d722e3fbSopenharmony_ci		 * running on an older kernel.
188d722e3fbSopenharmony_ci		 *
189d722e3fbSopenharmony_ci		 * To handle this issue, if using the older kernel interfaces,
190d722e3fbSopenharmony_ci		 * we'll magic up a list containing the vdec classes that the
191d722e3fbSopenharmony_ci		 * kernel will accept for these boards.  Clients should make
192d722e3fbSopenharmony_ci		 * use of this information instead of hardcoding classes for
193d722e3fbSopenharmony_ci		 * specific chipsets.
194d722e3fbSopenharmony_ci		 */
195d722e3fbSopenharmony_ci		dev = (struct nouveau_device *)obj->parent;
196d722e3fbSopenharmony_ci		if (dev->chipset >= 0x98 &&
197d722e3fbSopenharmony_ci		    dev->chipset != 0xa0 &&
198d722e3fbSopenharmony_ci		    dev->chipset <  0xc0) {
199d722e3fbSopenharmony_ci			*sclass++ = (struct nouveau_sclass){
200d722e3fbSopenharmony_ci				GT212_MSVLD, -1, -1
201d722e3fbSopenharmony_ci			};
202d722e3fbSopenharmony_ci			*sclass++ = (struct nouveau_sclass){
203d722e3fbSopenharmony_ci				GT212_MSPDEC, -1, -1
204d722e3fbSopenharmony_ci			};
205d722e3fbSopenharmony_ci			*sclass++ = (struct nouveau_sclass){
206d722e3fbSopenharmony_ci				GT212_MSPPP, -1, -1
207d722e3fbSopenharmony_ci			};
208d722e3fbSopenharmony_ci		}
209d722e3fbSopenharmony_ci		break;
210d722e3fbSopenharmony_ci	default:
211d722e3fbSopenharmony_ci		break;
212d722e3fbSopenharmony_ci	}
213d722e3fbSopenharmony_ci
214d722e3fbSopenharmony_ci	return sclass - *psclass;
215d722e3fbSopenharmony_ci}
216d722e3fbSopenharmony_ci
217d722e3fbSopenharmony_cidrm_private void
218d722e3fbSopenharmony_ciabi16_delete(struct nouveau_object *obj)
219d722e3fbSopenharmony_ci{
220d722e3fbSopenharmony_ci	struct nouveau_drm *drm = nouveau_drm(obj);
221d722e3fbSopenharmony_ci	if (obj->oclass == NOUVEAU_FIFO_CHANNEL_CLASS) {
222d722e3fbSopenharmony_ci		struct drm_nouveau_channel_free req;
223d722e3fbSopenharmony_ci		req.channel = obj->handle;
224d722e3fbSopenharmony_ci		drmCommandWrite(drm->fd, DRM_NOUVEAU_CHANNEL_FREE,
225d722e3fbSopenharmony_ci				&req, sizeof(req));
226d722e3fbSopenharmony_ci	} else {
227d722e3fbSopenharmony_ci		struct drm_nouveau_gpuobj_free req;
228d722e3fbSopenharmony_ci		req.channel = obj->parent->handle;
229d722e3fbSopenharmony_ci		req.handle  = obj->handle;
230d722e3fbSopenharmony_ci		drmCommandWrite(drm->fd, DRM_NOUVEAU_GPUOBJ_FREE,
231d722e3fbSopenharmony_ci				&req, sizeof(req));
232d722e3fbSopenharmony_ci	}
233d722e3fbSopenharmony_ci}
234d722e3fbSopenharmony_ci
235d722e3fbSopenharmony_cidrm_private bool
236d722e3fbSopenharmony_ciabi16_object(struct nouveau_object *obj, int (**func)(struct nouveau_object *))
237d722e3fbSopenharmony_ci{
238d722e3fbSopenharmony_ci	struct nouveau_object *parent = obj->parent;
239d722e3fbSopenharmony_ci
240d722e3fbSopenharmony_ci	/* nouveau_object::length is (ab)used to determine whether the
241d722e3fbSopenharmony_ci	 * object is a legacy object (!=0), or a real NVIF object.
242d722e3fbSopenharmony_ci	 */
243d722e3fbSopenharmony_ci	if ((parent->length != 0 && parent->oclass == NOUVEAU_DEVICE_CLASS) ||
244d722e3fbSopenharmony_ci	    (parent->length == 0 && parent->oclass == NV_DEVICE)) {
245d722e3fbSopenharmony_ci		if (obj->oclass == NOUVEAU_FIFO_CHANNEL_CLASS) {
246d722e3fbSopenharmony_ci			struct nouveau_device *dev = (void *)parent;
247d722e3fbSopenharmony_ci			if (dev->chipset < 0xc0)
248d722e3fbSopenharmony_ci				*func = abi16_chan_nv04;
249d722e3fbSopenharmony_ci			else
250d722e3fbSopenharmony_ci			if (dev->chipset < 0xe0)
251d722e3fbSopenharmony_ci				*func = abi16_chan_nvc0;
252d722e3fbSopenharmony_ci			else
253d722e3fbSopenharmony_ci				*func = abi16_chan_nve0;
254d722e3fbSopenharmony_ci			return true;
255d722e3fbSopenharmony_ci		}
256d722e3fbSopenharmony_ci	} else
257d722e3fbSopenharmony_ci	if ((parent->length != 0 &&
258d722e3fbSopenharmony_ci	     parent->oclass == NOUVEAU_FIFO_CHANNEL_CLASS)) {
259d722e3fbSopenharmony_ci		if (obj->oclass == NOUVEAU_NOTIFIER_CLASS) {
260d722e3fbSopenharmony_ci			*func = abi16_ntfy;
261d722e3fbSopenharmony_ci			return true;
262d722e3fbSopenharmony_ci		}
263d722e3fbSopenharmony_ci
264d722e3fbSopenharmony_ci		*func = abi16_engobj;
265d722e3fbSopenharmony_ci		return false; /* try NVIF, if supported, before calling func */
266d722e3fbSopenharmony_ci	}
267d722e3fbSopenharmony_ci
268d722e3fbSopenharmony_ci	*func = NULL;
269d722e3fbSopenharmony_ci	return false;
270d722e3fbSopenharmony_ci}
271d722e3fbSopenharmony_ci
272d722e3fbSopenharmony_cidrm_private void
273d722e3fbSopenharmony_ciabi16_bo_info(struct nouveau_bo *bo, struct drm_nouveau_gem_info *info)
274d722e3fbSopenharmony_ci{
275d722e3fbSopenharmony_ci	struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
276d722e3fbSopenharmony_ci
277d722e3fbSopenharmony_ci	nvbo->map_handle = info->map_handle;
278d722e3fbSopenharmony_ci	bo->handle = info->handle;
279d722e3fbSopenharmony_ci	bo->size = info->size;
280d722e3fbSopenharmony_ci	bo->offset = info->offset;
281d722e3fbSopenharmony_ci
282d722e3fbSopenharmony_ci	bo->flags = 0;
283d722e3fbSopenharmony_ci	if (info->domain & NOUVEAU_GEM_DOMAIN_VRAM)
284d722e3fbSopenharmony_ci		bo->flags |= NOUVEAU_BO_VRAM;
285d722e3fbSopenharmony_ci	if (info->domain & NOUVEAU_GEM_DOMAIN_GART)
286d722e3fbSopenharmony_ci		bo->flags |= NOUVEAU_BO_GART;
287d722e3fbSopenharmony_ci	if (!(info->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG))
288d722e3fbSopenharmony_ci		bo->flags |= NOUVEAU_BO_CONTIG;
289d722e3fbSopenharmony_ci	if (nvbo->map_handle)
290d722e3fbSopenharmony_ci		bo->flags |= NOUVEAU_BO_MAP;
291d722e3fbSopenharmony_ci
292d722e3fbSopenharmony_ci	if (bo->device->chipset >= 0xc0) {
293d722e3fbSopenharmony_ci		bo->config.nvc0.memtype   = (info->tile_flags & 0xff00) >> 8;
294d722e3fbSopenharmony_ci		bo->config.nvc0.tile_mode = info->tile_mode;
295d722e3fbSopenharmony_ci	} else
296d722e3fbSopenharmony_ci	if (bo->device->chipset >= 0x80 || bo->device->chipset == 0x50) {
297d722e3fbSopenharmony_ci		bo->config.nv50.memtype   = (info->tile_flags & 0x07f00) >> 8 |
298d722e3fbSopenharmony_ci					    (info->tile_flags & 0x30000) >> 9;
299d722e3fbSopenharmony_ci		bo->config.nv50.tile_mode = info->tile_mode << 4;
300d722e3fbSopenharmony_ci	} else {
301d722e3fbSopenharmony_ci		bo->config.nv04.surf_flags = info->tile_flags & 7;
302d722e3fbSopenharmony_ci		bo->config.nv04.surf_pitch = info->tile_mode;
303d722e3fbSopenharmony_ci	}
304d722e3fbSopenharmony_ci}
305d722e3fbSopenharmony_ci
306d722e3fbSopenharmony_cidrm_private int
307d722e3fbSopenharmony_ciabi16_bo_init(struct nouveau_bo *bo, uint32_t alignment,
308d722e3fbSopenharmony_ci	      union nouveau_bo_config *config)
309d722e3fbSopenharmony_ci{
310d722e3fbSopenharmony_ci	struct nouveau_device *dev = bo->device;
311d722e3fbSopenharmony_ci	struct nouveau_drm *drm = nouveau_drm(&dev->object);
312d722e3fbSopenharmony_ci	struct drm_nouveau_gem_new req = {};
313d722e3fbSopenharmony_ci	struct drm_nouveau_gem_info *info = &req.info;
314d722e3fbSopenharmony_ci	int ret;
315d722e3fbSopenharmony_ci
316d722e3fbSopenharmony_ci	if (bo->flags & NOUVEAU_BO_VRAM)
317d722e3fbSopenharmony_ci		info->domain |= NOUVEAU_GEM_DOMAIN_VRAM;
318d722e3fbSopenharmony_ci	if (bo->flags & NOUVEAU_BO_GART)
319d722e3fbSopenharmony_ci		info->domain |= NOUVEAU_GEM_DOMAIN_GART;
320d722e3fbSopenharmony_ci	if (!info->domain)
321d722e3fbSopenharmony_ci		info->domain |= NOUVEAU_GEM_DOMAIN_VRAM |
322d722e3fbSopenharmony_ci				NOUVEAU_GEM_DOMAIN_GART;
323d722e3fbSopenharmony_ci
324d722e3fbSopenharmony_ci	if (bo->flags & NOUVEAU_BO_MAP)
325d722e3fbSopenharmony_ci		info->domain |= NOUVEAU_GEM_DOMAIN_MAPPABLE;
326d722e3fbSopenharmony_ci
327d722e3fbSopenharmony_ci	if (bo->flags & NOUVEAU_BO_COHERENT)
328d722e3fbSopenharmony_ci		info->domain |= NOUVEAU_GEM_DOMAIN_COHERENT;
329d722e3fbSopenharmony_ci
330d722e3fbSopenharmony_ci	if (!(bo->flags & NOUVEAU_BO_CONTIG))
331d722e3fbSopenharmony_ci		info->tile_flags = NOUVEAU_GEM_TILE_NONCONTIG;
332d722e3fbSopenharmony_ci
333d722e3fbSopenharmony_ci	info->size = bo->size;
334d722e3fbSopenharmony_ci	req.align = alignment;
335d722e3fbSopenharmony_ci
336d722e3fbSopenharmony_ci	if (config) {
337d722e3fbSopenharmony_ci		if (dev->chipset >= 0xc0) {
338d722e3fbSopenharmony_ci			info->tile_flags = (config->nvc0.memtype & 0xff) << 8;
339d722e3fbSopenharmony_ci			info->tile_mode  = config->nvc0.tile_mode;
340d722e3fbSopenharmony_ci		} else
341d722e3fbSopenharmony_ci		if (dev->chipset >= 0x80 || dev->chipset == 0x50) {
342d722e3fbSopenharmony_ci			info->tile_flags = (config->nv50.memtype & 0x07f) << 8 |
343d722e3fbSopenharmony_ci					   (config->nv50.memtype & 0x180) << 9;
344d722e3fbSopenharmony_ci			info->tile_mode  = config->nv50.tile_mode >> 4;
345d722e3fbSopenharmony_ci		} else {
346d722e3fbSopenharmony_ci			info->tile_flags = config->nv04.surf_flags & 7;
347d722e3fbSopenharmony_ci			info->tile_mode  = config->nv04.surf_pitch;
348d722e3fbSopenharmony_ci		}
349d722e3fbSopenharmony_ci	}
350d722e3fbSopenharmony_ci
351d722e3fbSopenharmony_ci	if (!nouveau_device(dev)->have_bo_usage)
352d722e3fbSopenharmony_ci		info->tile_flags &= 0x0000ff00;
353d722e3fbSopenharmony_ci
354d722e3fbSopenharmony_ci	ret = drmCommandWriteRead(drm->fd, DRM_NOUVEAU_GEM_NEW,
355d722e3fbSopenharmony_ci				  &req, sizeof(req));
356d722e3fbSopenharmony_ci	if (ret == 0)
357d722e3fbSopenharmony_ci		abi16_bo_info(bo, &req.info);
358d722e3fbSopenharmony_ci	return ret;
359d722e3fbSopenharmony_ci}
360