nouveau_copy.c revision 16ee1e9a
1/*
2 * Copyright 2014 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs <bskeggs@redhat.com>
23 */
24
25#include "nouveau_copy.h"
26
27void
28nouveau_copy_fini(ScreenPtr pScreen)
29{
30	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
31	NVPtr pNv = NVPTR(pScrn);
32	nouveau_object_del(&pNv->NvCopy);
33	nouveau_pushbuf_del(&pNv->ce_pushbuf);
34	nouveau_object_del(&pNv->ce_channel);
35}
36
37Bool
38nouveau_copy_init(ScreenPtr pScreen)
39{
40	static const struct {
41		CARD32 oclass;
42		int engine;
43		Bool (*init)(NVPtr);
44	} methods[] = {
45		{ 0xa0b5, 0, nouveau_copya0b5_init },
46		{ 0x90b8, 5, nouveau_copy90b5_init },
47		{ 0x90b5, 4, nouveau_copy90b5_init },
48		{ 0x85b5, 0, nouveau_copy85b5_init },
49		{}
50	}, *method = methods;
51	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
52	NVPtr pNv = NVPTR(pScrn);
53	void *data;
54	int ret, size;
55
56	if (pNv->AccelMethod == NONE) {
57		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
58			   "[COPY] acceleration disabled\n");
59		return FALSE;
60	}
61
62	switch (pNv->Architecture) {
63	case NV_TESLA:
64		if (pNv->dev->chipset < 0xa3 ||
65		    pNv->dev->chipset == 0xaa ||
66		    pNv->dev->chipset == 0xac)
67			return FALSE;
68		data = &(struct nv04_fifo) {
69			.vram = NvDmaFB,
70			.gart = NvDmaTT,
71		};
72		size = sizeof(struct nv04_fifo);
73		break;
74	case NV_FERMI:
75		data = &(struct nvc0_fifo) {};
76		size = sizeof(struct nvc0_fifo);
77		break;
78	case NV_KEPLER:
79		data = &(struct nve0_fifo) {
80			.engine = NVE0_FIFO_ENGINE_CE0 |
81				  NVE0_FIFO_ENGINE_CE1,
82		};
83		size = sizeof(struct nvc0_fifo);
84		break;
85	default:
86		return FALSE;
87	}
88
89	ret = nouveau_object_new(&pNv->dev->object, 0,
90				 NOUVEAU_FIFO_CHANNEL_CLASS, data, size,
91				 &pNv->ce_channel);
92	if (ret) {
93		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
94			   "[COPY] error allocating channel: %d\n", ret);
95		return FALSE;
96	}
97
98	ret = nouveau_pushbuf_new(pNv->client, pNv->ce_channel, 4,
99				  32 * 1024, true, &pNv->ce_pushbuf);
100	if (ret) {
101		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
102			   "[COPY] error allocating pushbuf: %d\n", ret);
103		nouveau_copy_fini(pScreen);
104		return FALSE;
105	}
106
107	while (method->init) {
108		ret = nouveau_object_new(pNv->ce_channel,
109					 method->engine << 16 | method->oclass,
110					 method->oclass, NULL, 0,
111					 &pNv->NvCopy);
112		if (ret == 0) {
113			if (!method->init(pNv)) {
114				xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
115					   "[COPY] failed to initialise.\n");
116				nouveau_copy_fini(pScreen);
117				return FALSE;
118			}
119			break;
120		}
121		method++;
122	}
123
124	if (ret) {
125		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
126			   "[COPY] failed to allocate class.\n");
127		nouveau_copy_fini(pScreen);
128		return FALSE;
129	}
130
131	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[COPY] async initialised.\n");
132	return TRUE;
133}
134