1428d7b3dSmrg/*
2428d7b3dSmrg * Copyright © 2007 Intel Corporation
3428d7b3dSmrg *
4428d7b3dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
5428d7b3dSmrg * copy of this software and associated documentation files (the "Software"),
6428d7b3dSmrg * to deal in the Software without restriction, including without limitation
7428d7b3dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8428d7b3dSmrg * and/or sell copies of the Software, and to permit persons to whom the
9428d7b3dSmrg * Software is furnished to do so, subject to the following conditions:
10428d7b3dSmrg *
11428d7b3dSmrg * The above copyright notice and this permission notice (including the next
12428d7b3dSmrg * paragraph) shall be included in all copies or substantial portions of the
13428d7b3dSmrg * Software.
14428d7b3dSmrg *
15428d7b3dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16428d7b3dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17428d7b3dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18428d7b3dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19428d7b3dSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20428d7b3dSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21428d7b3dSmrg * SOFTWARE.
22428d7b3dSmrg *
23428d7b3dSmrg * Authors:
24428d7b3dSmrg *    Zhenyu Wang <zhenyu.z.wang@sna.com>
25428d7b3dSmrg *
26428d7b3dSmrg */
27428d7b3dSmrg#ifdef HAVE_CONFIG_H
28428d7b3dSmrg#include "config.h"
29428d7b3dSmrg#endif
30428d7b3dSmrg
31428d7b3dSmrg#define _SNA_XVMC_SERVER_
32428d7b3dSmrg#include "sna.h"
33428d7b3dSmrg#include "sna_video_hwmc.h"
34428d7b3dSmrg
35428d7b3dSmrg#include <X11/extensions/Xv.h>
36428d7b3dSmrg#include <X11/extensions/XvMC.h>
37428d7b3dSmrg#include <fourcc.h>
38428d7b3dSmrg
39428d7b3dSmrgextern DevPrivateKey XF86XvScreenKey;
40428d7b3dSmrg
41428d7b3dSmrgstatic int create_subpicture(XvMCSubpicturePtr sub, int *size, CARD32 **priv)
42428d7b3dSmrg{
43428d7b3dSmrg	return Success;
44428d7b3dSmrg}
45428d7b3dSmrg
46428d7b3dSmrgstatic void destroy_subpicture(XvMCSubpicturePtr sub)
47428d7b3dSmrg{
48428d7b3dSmrg}
49428d7b3dSmrg
50428d7b3dSmrgstatic int create_surface(XvMCSurfacePtr surface, int *size, CARD32 **priv)
51428d7b3dSmrg{
52428d7b3dSmrg	return Success;
53428d7b3dSmrg}
54428d7b3dSmrg
55428d7b3dSmrgstatic void destroy_surface(XvMCSurfacePtr surface)
56428d7b3dSmrg{
57428d7b3dSmrg}
58428d7b3dSmrg
59428d7b3dSmrgstatic int create_context(XvPortPtr port, XvMCContextPtr ctx,
60428d7b3dSmrg			  int *size, CARD32 **out)
61428d7b3dSmrg{
62428d7b3dSmrg	struct sna *sna = to_sna_from_screen(ctx->pScreen);
63428d7b3dSmrg	struct intel_xvmc_hw_context {
64428d7b3dSmrg		unsigned int type;
65428d7b3dSmrg		union {
66428d7b3dSmrg			struct {
67428d7b3dSmrg				unsigned int use_phys_addr : 1;
68428d7b3dSmrg			} i915;
69428d7b3dSmrg			struct {
70428d7b3dSmrg				unsigned int is_g4x:1;
71428d7b3dSmrg				unsigned int is_965_q:1;
72428d7b3dSmrg				unsigned int is_igdng:1;
73428d7b3dSmrg			} i965;
74428d7b3dSmrg		};
75428d7b3dSmrg	} *priv;
76428d7b3dSmrg
77428d7b3dSmrg	ctx->port_priv = port->devPriv.ptr;
78428d7b3dSmrg
79428d7b3dSmrg	priv = calloc(1, sizeof(*priv));
80428d7b3dSmrg	if (priv == NULL)
81428d7b3dSmrg		return BadAlloc;
82428d7b3dSmrg
83428d7b3dSmrg	if (sna->kgem.gen >= 040) {
84428d7b3dSmrg		int devid = intel_get_device_id(sna->dev);
85428d7b3dSmrg
86428d7b3dSmrg		if (sna->kgem.gen >= 045)
87428d7b3dSmrg			priv->type = XVMC_I965_MPEG2_VLD;
88428d7b3dSmrg		else
89428d7b3dSmrg			priv->type = XVMC_I965_MPEG2_MC;
90428d7b3dSmrg		priv->i965.is_g4x = sna->kgem.gen == 045;
91428d7b3dSmrg		priv->i965.is_965_q = devid == PCI_CHIP_I965_Q;
92428d7b3dSmrg		priv->i965.is_igdng = sna->kgem.gen == 050;
93428d7b3dSmrg	} else
94428d7b3dSmrg		priv->type = XVMC_I915_MPEG2_MC;
95428d7b3dSmrg
96428d7b3dSmrg	*size = sizeof(*priv) >> 2;
97428d7b3dSmrg	*out = (CARD32 *)priv;
98428d7b3dSmrg	return Success;
99428d7b3dSmrg}
100428d7b3dSmrg
101428d7b3dSmrgstatic void destroy_context(XvMCContextPtr ctx)
102428d7b3dSmrg{
103428d7b3dSmrg}
104428d7b3dSmrg
105428d7b3dSmrg/* i915 hwmc support */
106428d7b3dSmrgstatic XvMCSurfaceInfoRec i915_YV12_mpg2_surface = {
107428d7b3dSmrg	FOURCC_YV12,
108428d7b3dSmrg	XVMC_CHROMA_FORMAT_420,
109428d7b3dSmrg	0,
110428d7b3dSmrg	720,
111428d7b3dSmrg	576,
112428d7b3dSmrg	720,
113428d7b3dSmrg	576,
114428d7b3dSmrg	XVMC_MPEG_2,
115428d7b3dSmrg	/* XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING, */
116428d7b3dSmrg	0,
117428d7b3dSmrg	/* &yv12_subpicture_list */
118428d7b3dSmrg	NULL,
119428d7b3dSmrg};
120428d7b3dSmrg
121428d7b3dSmrgstatic XvMCSurfaceInfoRec i915_YV12_mpg1_surface = {
122428d7b3dSmrg	FOURCC_YV12,
123428d7b3dSmrg	XVMC_CHROMA_FORMAT_420,
124428d7b3dSmrg	0,
125428d7b3dSmrg	720,
126428d7b3dSmrg	576,
127428d7b3dSmrg	720,
128428d7b3dSmrg	576,
129428d7b3dSmrg	XVMC_MPEG_1,
130428d7b3dSmrg	/* XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING, */
131428d7b3dSmrg	0,
132428d7b3dSmrg	NULL,
133428d7b3dSmrg};
134428d7b3dSmrg
135428d7b3dSmrgstatic XvMCSurfaceInfoPtr surface_info_i915[2] = {
136428d7b3dSmrg	&i915_YV12_mpg2_surface,
137428d7b3dSmrg	&i915_YV12_mpg1_surface
138428d7b3dSmrg};
139428d7b3dSmrg
140428d7b3dSmrg/* i965 and later hwmc support */
141428d7b3dSmrg#ifndef XVMC_VLD
142428d7b3dSmrg#define XVMC_VLD  0x00020000
143428d7b3dSmrg#endif
144428d7b3dSmrg
145428d7b3dSmrgstatic XvMCSurfaceInfoRec yv12_mpeg2_vld_surface = {
146428d7b3dSmrg	FOURCC_YV12,
147428d7b3dSmrg	XVMC_CHROMA_FORMAT_420,
148428d7b3dSmrg	0,
149428d7b3dSmrg	1936,
150428d7b3dSmrg	1096,
151428d7b3dSmrg	1920,
152428d7b3dSmrg	1080,
153428d7b3dSmrg	XVMC_MPEG_2 | XVMC_VLD,
154428d7b3dSmrg	XVMC_INTRA_UNSIGNED,
155428d7b3dSmrg	NULL
156428d7b3dSmrg};
157428d7b3dSmrg
158428d7b3dSmrgstatic XvMCSurfaceInfoRec yv12_mpeg2_i965_surface = {
159428d7b3dSmrg	FOURCC_YV12,
160428d7b3dSmrg	XVMC_CHROMA_FORMAT_420,
161428d7b3dSmrg	0,
162428d7b3dSmrg	1936,
163428d7b3dSmrg	1096,
164428d7b3dSmrg	1920,
165428d7b3dSmrg	1080,
166428d7b3dSmrg	XVMC_MPEG_2 | XVMC_MOCOMP,
167428d7b3dSmrg	/* XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING, */
168428d7b3dSmrg	XVMC_INTRA_UNSIGNED,
169428d7b3dSmrg	/* &yv12_subpicture_list */
170428d7b3dSmrg	NULL
171428d7b3dSmrg};
172428d7b3dSmrg
173428d7b3dSmrgstatic XvMCSurfaceInfoRec yv12_mpeg1_i965_surface = {
174428d7b3dSmrg	FOURCC_YV12,
175428d7b3dSmrg	XVMC_CHROMA_FORMAT_420,
176428d7b3dSmrg	0,
177428d7b3dSmrg	1920,
178428d7b3dSmrg	1080,
179428d7b3dSmrg	1920,
180428d7b3dSmrg	1080,
181428d7b3dSmrg	XVMC_MPEG_1 | XVMC_MOCOMP,
182428d7b3dSmrg	/*XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING |
183428d7b3dSmrg	   XVMC_INTRA_UNSIGNED, */
184428d7b3dSmrg	XVMC_INTRA_UNSIGNED,
185428d7b3dSmrg
186428d7b3dSmrg	/*&yv12_subpicture_list */
187428d7b3dSmrg	NULL
188428d7b3dSmrg};
189428d7b3dSmrg
190428d7b3dSmrgstatic XvMCSurfaceInfoPtr surface_info_i965[] = {
191428d7b3dSmrg	&yv12_mpeg2_i965_surface,
192428d7b3dSmrg	&yv12_mpeg1_i965_surface
193428d7b3dSmrg};
194428d7b3dSmrg
195428d7b3dSmrgstatic XvMCSurfaceInfoPtr surface_info_vld[] = {
196428d7b3dSmrg	&yv12_mpeg2_vld_surface,
197428d7b3dSmrg	&yv12_mpeg2_i965_surface,
198428d7b3dSmrg};
199428d7b3dSmrg
200428d7b3dSmrg/* check chip type and load xvmc driver */
201428d7b3dSmrgvoid sna_video_xvmc_setup(struct sna *sna, ScreenPtr screen)
202428d7b3dSmrg{
203428d7b3dSmrg	XvMCAdaptorRec *adaptors;
204428d7b3dSmrg	struct pci_device *pci;
205428d7b3dSmrg	const char *name;
206428d7b3dSmrg	char bus[64];
207428d7b3dSmrg	int i;
208428d7b3dSmrg
209428d7b3dSmrg	pci = xf86GetPciInfoForEntity(sna->pEnt->index);
210428d7b3dSmrg	if (pci == NULL)
211428d7b3dSmrg		return;
212428d7b3dSmrg
213428d7b3dSmrg	if (!sna->xv.num_adaptors)
214428d7b3dSmrg		return;
215428d7b3dSmrg
216428d7b3dSmrg	if (!xf86LoaderCheckSymbol("XvMCScreenInit"))
217428d7b3dSmrg		return;
218428d7b3dSmrg
219428d7b3dSmrg	/* Needs KMS support. */
220428d7b3dSmrg	if (sna->kgem.gen < 031)
221428d7b3dSmrg		return;
222428d7b3dSmrg
223428d7b3dSmrg	/* Not implemented */
224428d7b3dSmrg	if (sna->kgem.gen >= 060)
225428d7b3dSmrg		return;
226428d7b3dSmrg
227428d7b3dSmrg	adaptors = calloc(sna->xv.num_adaptors, sizeof(XvMCAdaptorRec));
228428d7b3dSmrg	if (adaptors == NULL)
229428d7b3dSmrg		return;
230428d7b3dSmrg
231428d7b3dSmrg	for (i = 0; i< sna->xv.num_adaptors; i++) {
232428d7b3dSmrg		adaptors[i].xv_adaptor = &sna->xv.adaptors[i];
233428d7b3dSmrg
234428d7b3dSmrg		adaptors[i].num_subpictures = 0;
235428d7b3dSmrg		adaptors[i].subpictures = NULL;
236428d7b3dSmrg		adaptors[i].CreateContext = create_context;
237428d7b3dSmrg		adaptors[i].DestroyContext = destroy_context;
238428d7b3dSmrg		adaptors[i].CreateSurface = create_surface;
239428d7b3dSmrg		adaptors[i].DestroySurface = destroy_surface;
240428d7b3dSmrg		adaptors[i].CreateSubpicture = create_subpicture;
241428d7b3dSmrg		adaptors[i].DestroySubpicture = destroy_subpicture;
242428d7b3dSmrg
243428d7b3dSmrg		if (sna->kgem.gen >= 045) {
244428d7b3dSmrg			adaptors[i].num_surfaces = ARRAY_SIZE(surface_info_vld);
245428d7b3dSmrg			adaptors[i].surfaces = surface_info_vld;
246428d7b3dSmrg		} else if (sna->kgem.gen >= 040) {
247428d7b3dSmrg			adaptors[i].num_surfaces = ARRAY_SIZE(surface_info_i965);
248428d7b3dSmrg			adaptors[i].surfaces = surface_info_i965;
249428d7b3dSmrg		} else {
250428d7b3dSmrg			adaptors[i].num_surfaces = ARRAY_SIZE(surface_info_i915);
251428d7b3dSmrg			adaptors[i].surfaces = surface_info_i915;
252428d7b3dSmrg		}
253428d7b3dSmrg	}
254428d7b3dSmrg
255428d7b3dSmrg	if (XvMCScreenInit(screen, i, adaptors) != Success) {
256428d7b3dSmrg		xf86DrvMsg(sna->scrn->scrnIndex, X_INFO,
257428d7b3dSmrg			   "[XvMC] Failed to initialize XvMC.\n");
258428d7b3dSmrg		free(adaptors);
259428d7b3dSmrg		return;
260428d7b3dSmrg	}
261428d7b3dSmrg
262428d7b3dSmrg	sprintf(bus, "pci:%04x:%02x:%02x.%d",
263428d7b3dSmrg		pci->domain, pci->bus, pci->dev, pci->func);
264428d7b3dSmrg
265428d7b3dSmrg	xf86XvMCRegisterDRInfo(screen, (char *)SNA_XVMC_LIBNAME, bus,
266428d7b3dSmrg			       SNA_XVMC_MAJOR, SNA_XVMC_MINOR,
267428d7b3dSmrg			       SNA_XVMC_PATCHLEVEL);
268428d7b3dSmrg
269428d7b3dSmrg	if (sna->kgem.gen >= 045)
270428d7b3dSmrg		name = "xvmc_vld";
271428d7b3dSmrg	else if (sna->kgem.gen >= 040)
272428d7b3dSmrg		name = "i965_xvmc";
273428d7b3dSmrg	else
274428d7b3dSmrg		name = "i915_xvmc";
275428d7b3dSmrg	xf86DrvMsg(sna->scrn->scrnIndex, X_INFO,
276428d7b3dSmrg		   "[XvMC] %s driver initialized.\n",
277428d7b3dSmrg		   name);
278428d7b3dSmrg}
279