1/*
2 * Copyright © 2007 Intel Corporation
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 (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 *    Zhenyu Wang <zhenyu.z.wang@intel.com>
25 *
26 */
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif
30
31#define _INTEL_XVMC_SERVER_
32#include "intel.h"
33#include "intel_xvmc.h"
34
35#include <X11/extensions/Xv.h>
36#include <X11/extensions/XvMC.h>
37#include <fourcc.h>
38
39static int create_subpicture(ScrnInfoPtr scrn, XvMCSubpicturePtr subpicture,
40			     int *num_priv, CARD32 ** priv)
41{
42	return Success;
43}
44
45static void destroy_subpicture(ScrnInfoPtr scrn, XvMCSubpicturePtr subpicture)
46{
47}
48
49static int create_surface(ScrnInfoPtr scrn, XvMCSurfacePtr surface,
50			  int *num_priv, CARD32 ** priv)
51{
52	return Success;
53}
54
55static void destroy_surface(ScrnInfoPtr scrn, XvMCSurfacePtr surface)
56{
57}
58
59static int create_context(ScrnInfoPtr scrn, XvMCContextPtr pContext,
60				    int *num_priv, CARD32 **priv)
61{
62	intel_screen_private *intel = intel_get_screen_private(scrn);
63	struct intel_xvmc_hw_context *contextRec;
64
65	*priv = calloc(1, sizeof(struct intel_xvmc_hw_context));
66	contextRec = (struct intel_xvmc_hw_context *) *priv;
67	if (!contextRec) {
68		*num_priv = 0;
69		return BadAlloc;
70	}
71
72	*num_priv = sizeof(struct intel_xvmc_hw_context) >> 2;
73
74	if (IS_GEN3(intel)) {
75		contextRec->type = XVMC_I915_MPEG2_MC;
76		contextRec->i915.use_phys_addr = 0;
77	} else {
78		if (INTEL_INFO(intel)->gen >= 045)
79			contextRec->type = XVMC_I965_MPEG2_VLD;
80		else
81			contextRec->type = XVMC_I965_MPEG2_MC;
82		contextRec->i965.is_g4x = INTEL_INFO(intel)->gen == 045;
83		contextRec->i965.is_965_q = IS_965_Q(intel);
84		contextRec->i965.is_igdng = IS_GEN5(intel);
85	}
86
87	return Success;
88}
89
90static void destroy_context(ScrnInfoPtr scrn, XvMCContextPtr context)
91{
92}
93
94/* i915 hwmc support */
95static XF86MCSurfaceInfoRec i915_YV12_mpg2_surface = {
96	FOURCC_YV12,
97	XVMC_CHROMA_FORMAT_420,
98	0,
99	720,
100	576,
101	720,
102	576,
103	XVMC_MPEG_2,
104	/* XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING, */
105	0,
106	/* &yv12_subpicture_list */
107	NULL,
108};
109
110static XF86MCSurfaceInfoRec i915_YV12_mpg1_surface = {
111	FOURCC_YV12,
112	XVMC_CHROMA_FORMAT_420,
113	0,
114	720,
115	576,
116	720,
117	576,
118	XVMC_MPEG_1,
119	/* XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING, */
120	0,
121	NULL,
122};
123
124static XF86MCSurfaceInfoPtr surface_info_i915[2] = {
125	(XF86MCSurfaceInfoPtr) & i915_YV12_mpg2_surface,
126	(XF86MCSurfaceInfoPtr) & i915_YV12_mpg1_surface
127};
128
129/* i965 and later hwmc support */
130#ifndef XVMC_VLD
131#define XVMC_VLD  0x00020000
132#endif
133
134static XF86MCSurfaceInfoRec yv12_mpeg2_vld_surface = {
135	FOURCC_YV12,
136	XVMC_CHROMA_FORMAT_420,
137	0,
138	1936,
139	1096,
140	1920,
141	1080,
142	XVMC_MPEG_2 | XVMC_VLD,
143	XVMC_INTRA_UNSIGNED,
144	NULL
145};
146
147static XF86MCSurfaceInfoRec yv12_mpeg2_i965_surface = {
148	FOURCC_YV12,
149	XVMC_CHROMA_FORMAT_420,
150	0,
151	1936,
152	1096,
153	1920,
154	1080,
155	XVMC_MPEG_2 | XVMC_MOCOMP,
156	/* XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING, */
157	XVMC_INTRA_UNSIGNED,
158	/* &yv12_subpicture_list */
159	NULL
160};
161
162static XF86MCSurfaceInfoRec yv12_mpeg1_i965_surface = {
163	FOURCC_YV12,
164	XVMC_CHROMA_FORMAT_420,
165	0,
166	1920,
167	1080,
168	1920,
169	1080,
170	XVMC_MPEG_1 | XVMC_MOCOMP,
171	/*XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING |
172	   XVMC_INTRA_UNSIGNED, */
173	XVMC_INTRA_UNSIGNED,
174
175	/*&yv12_subpicture_list */
176	NULL
177};
178
179static XF86MCSurfaceInfoPtr surface_info_i965[] = {
180	&yv12_mpeg2_i965_surface,
181	&yv12_mpeg1_i965_surface
182};
183
184static XF86MCSurfaceInfoPtr surface_info_vld[] = {
185	&yv12_mpeg2_vld_surface,
186	&yv12_mpeg2_i965_surface,
187};
188
189/* check chip type and load xvmc driver */
190Bool intel_xvmc_adaptor_init(ScreenPtr pScreen)
191{
192	ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
193	intel_screen_private *intel = intel_get_screen_private(scrn);
194	struct pci_device *pci;
195	static XF86MCAdaptorRec *pAdapt;
196	const char *name;
197	char buf[64];
198
199	if (!intel->XvMCEnabled)
200		return FALSE;
201
202	/* Needs KMS support. */
203	if (IS_I915G(intel) || IS_I915GM(intel))
204		return FALSE;
205
206	if (IS_GEN2(intel)) {
207		ErrorF("Your chipset doesn't support XvMC.\n");
208		return FALSE;
209	}
210
211	pci = xf86GetPciInfoForEntity(intel->pEnt->index);
212	if (pci == NULL)
213		return FALSE;
214
215	pAdapt = calloc(1, sizeof(XF86MCAdaptorRec));
216	if (!pAdapt) {
217		ErrorF("Allocation error.\n");
218		return FALSE;
219	}
220
221	pAdapt->name = "Intel(R) Textured Video";
222	pAdapt->num_subpictures = 0;
223	pAdapt->subpictures = NULL;
224	pAdapt->CreateContext = create_context;
225	pAdapt->DestroyContext = destroy_context;
226	pAdapt->CreateSurface = create_surface;
227	pAdapt->DestroySurface = destroy_surface;
228	pAdapt->CreateSubpicture =  create_subpicture;
229	pAdapt->DestroySubpicture = destroy_subpicture;
230
231	if (IS_GEN3(intel)) {
232		name = "i915_xvmc",
233		pAdapt->num_surfaces = ARRAY_SIZE(surface_info_i915);
234		pAdapt->surfaces = surface_info_i915;
235	} else if (INTEL_INFO(intel)->gen >= 045) {
236		name = "xvmc_vld",
237		pAdapt->num_surfaces = ARRAY_SIZE(surface_info_vld);
238		pAdapt->surfaces = surface_info_vld;
239	} else {
240		name = "i965_xvmc",
241		pAdapt->num_surfaces = ARRAY_SIZE(surface_info_i965);
242		pAdapt->surfaces = surface_info_i965;
243	}
244
245	if (xf86XvMCScreenInit(pScreen, 1, &pAdapt)) {
246		xf86DrvMsg(scrn->scrnIndex, X_INFO,
247			   "[XvMC] %s driver initialized.\n",
248			   name);
249	} else {
250		intel->XvMCEnabled = FALSE;
251		xf86DrvMsg(scrn->scrnIndex, X_INFO,
252			   "[XvMC] Failed to initialize XvMC.\n");
253		return FALSE;
254	}
255
256	sprintf(buf, "pci:%04x:%02x:%02x.%d",
257		pci->domain, pci->bus, pci->dev, pci->func);
258
259	xf86XvMCRegisterDRInfo(pScreen, INTEL_XVMC_LIBNAME,
260			       buf,
261			       INTEL_XVMC_MAJOR, INTEL_XVMC_MINOR,
262			       INTEL_XVMC_PATCHLEVEL);
263	return TRUE;
264}
265