nouveau_copy.c revision fda9279d
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		data = &(struct nv04_fifo) {
65			.vram = NvDmaFB,
66			.gart = NvDmaTT,
67		};
68		size = sizeof(struct nv04_fifo);
69		break;
70	case NV_FERMI:
71		data = &(struct nvc0_fifo) {};
72		size = sizeof(struct nvc0_fifo);
73		break;
74	case NV_KEPLER:
75		data = &(struct nve0_fifo) {
76			.engine = NVE0_FIFO_ENGINE_CE0 |
77				  NVE0_FIFO_ENGINE_CE1,
78		};
79		size = sizeof(struct nvc0_fifo);
80		break;
81	default:
82		return FALSE;
83	}
84
85	ret = nouveau_object_new(&pNv->dev->object, 0,
86				 NOUVEAU_FIFO_CHANNEL_CLASS, data, size,
87				 &pNv->ce_channel);
88	if (ret) {
89		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
90			   "[COPY} error allocating channel: %d\n", ret);
91		return FALSE;
92	}
93
94	ret = nouveau_pushbuf_new(pNv->client, pNv->ce_channel, 4,
95				  32 * 1024, true, &pNv->ce_pushbuf);
96	if (ret) {
97		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
98			   "[COPY] error allocating pushbuf: %d\n", ret);
99		nouveau_copy_fini(pScreen);
100		return FALSE;
101	}
102
103	while (method->init) {
104		ret = nouveau_object_new(pNv->ce_channel,
105					 method->engine << 16 | method->oclass,
106					 method->oclass, NULL, 0,
107					 &pNv->NvCopy);
108		if (ret == 0) {
109			if (!method->init(pNv)) {
110				xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
111					   "[COPY] failed to initialise.\n");
112				nouveau_copy_fini(pScreen);
113				return FALSE;
114			}
115			break;
116		}
117		method++;
118	}
119
120	if (ret) {
121		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
122			   "[COPY] failed to allocate class.\n");
123		nouveau_copy_fini(pScreen);
124		return FALSE;
125	}
126
127	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[COPY] async initialised.\n");
128	return TRUE;
129}
130