103b705cfSriastradh/*
203b705cfSriastradh * Copyright © 2007 Intel Corporation
303b705cfSriastradh *
403b705cfSriastradh * Permission is hereby granted, free of charge, to any person obtaining a
503b705cfSriastradh * copy of this software and associated documentation files (the "Software"),
603b705cfSriastradh * to deal in the Software without restriction, including without limitation
703b705cfSriastradh * the rights to use, copy, modify, merge, publish, distribute, sublicense,
803b705cfSriastradh * and/or sell copies of the Software, and to permit persons to whom the
903b705cfSriastradh * Software is furnished to do so, subject to the following conditions:
1003b705cfSriastradh *
1103b705cfSriastradh * The above copyright notice and this permission notice (including the next
1203b705cfSriastradh * paragraph) shall be included in all copies or substantial portions of the
1303b705cfSriastradh * Software.
1403b705cfSriastradh *
1503b705cfSriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1603b705cfSriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1703b705cfSriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1803b705cfSriastradh * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1903b705cfSriastradh * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2003b705cfSriastradh * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2103b705cfSriastradh * SOFTWARE.
2203b705cfSriastradh *
2303b705cfSriastradh * Authors:
2403b705cfSriastradh *    Zhenyu Wang <zhenyu.z.wang@intel.com>
2503b705cfSriastradh *
2603b705cfSriastradh */
2703b705cfSriastradh#ifdef HAVE_CONFIG_H
2803b705cfSriastradh#include "config.h"
2903b705cfSriastradh#endif
3003b705cfSriastradh
3103b705cfSriastradh#define _INTEL_XVMC_SERVER_
3203b705cfSriastradh#include "intel.h"
3303b705cfSriastradh#include "intel_xvmc.h"
3403b705cfSriastradh
3503b705cfSriastradh#include <X11/extensions/Xv.h>
3603b705cfSriastradh#include <X11/extensions/XvMC.h>
3703b705cfSriastradh#include <fourcc.h>
3803b705cfSriastradh
3903b705cfSriastradhstatic int create_subpicture(ScrnInfoPtr scrn, XvMCSubpicturePtr subpicture,
4003b705cfSriastradh			     int *num_priv, CARD32 ** priv)
4103b705cfSriastradh{
4203b705cfSriastradh	return Success;
4303b705cfSriastradh}
4403b705cfSriastradh
4503b705cfSriastradhstatic void destroy_subpicture(ScrnInfoPtr scrn, XvMCSubpicturePtr subpicture)
4603b705cfSriastradh{
4703b705cfSriastradh}
4803b705cfSriastradh
4903b705cfSriastradhstatic int create_surface(ScrnInfoPtr scrn, XvMCSurfacePtr surface,
5003b705cfSriastradh			  int *num_priv, CARD32 ** priv)
5103b705cfSriastradh{
5203b705cfSriastradh	return Success;
5303b705cfSriastradh}
5403b705cfSriastradh
5503b705cfSriastradhstatic void destroy_surface(ScrnInfoPtr scrn, XvMCSurfacePtr surface)
5603b705cfSriastradh{
5703b705cfSriastradh}
5803b705cfSriastradh
5903b705cfSriastradhstatic int create_context(ScrnInfoPtr scrn, XvMCContextPtr pContext,
6003b705cfSriastradh				    int *num_priv, CARD32 **priv)
6103b705cfSriastradh{
6203b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
6303b705cfSriastradh	struct intel_xvmc_hw_context *contextRec;
6403b705cfSriastradh
6503b705cfSriastradh	*priv = calloc(1, sizeof(struct intel_xvmc_hw_context));
6603b705cfSriastradh	contextRec = (struct intel_xvmc_hw_context *) *priv;
6703b705cfSriastradh	if (!contextRec) {
6803b705cfSriastradh		*num_priv = 0;
6903b705cfSriastradh		return BadAlloc;
7003b705cfSriastradh	}
7103b705cfSriastradh
7203b705cfSriastradh	*num_priv = sizeof(struct intel_xvmc_hw_context) >> 2;
7303b705cfSriastradh
7403b705cfSriastradh	if (IS_GEN3(intel)) {
7503b705cfSriastradh		contextRec->type = XVMC_I915_MPEG2_MC;
7603b705cfSriastradh		contextRec->i915.use_phys_addr = 0;
7703b705cfSriastradh	} else {
7803b705cfSriastradh		if (INTEL_INFO(intel)->gen >= 045)
7903b705cfSriastradh			contextRec->type = XVMC_I965_MPEG2_VLD;
8003b705cfSriastradh		else
8103b705cfSriastradh			contextRec->type = XVMC_I965_MPEG2_MC;
8203b705cfSriastradh		contextRec->i965.is_g4x = INTEL_INFO(intel)->gen == 045;
8303b705cfSriastradh		contextRec->i965.is_965_q = IS_965_Q(intel);
8403b705cfSriastradh		contextRec->i965.is_igdng = IS_GEN5(intel);
8503b705cfSriastradh	}
8603b705cfSriastradh
8703b705cfSriastradh	return Success;
8803b705cfSriastradh}
8903b705cfSriastradh
9003b705cfSriastradhstatic void destroy_context(ScrnInfoPtr scrn, XvMCContextPtr context)
9103b705cfSriastradh{
9203b705cfSriastradh}
9303b705cfSriastradh
9403b705cfSriastradh/* i915 hwmc support */
9503b705cfSriastradhstatic XF86MCSurfaceInfoRec i915_YV12_mpg2_surface = {
9603b705cfSriastradh	FOURCC_YV12,
9703b705cfSriastradh	XVMC_CHROMA_FORMAT_420,
9803b705cfSriastradh	0,
9903b705cfSriastradh	720,
10003b705cfSriastradh	576,
10103b705cfSriastradh	720,
10203b705cfSriastradh	576,
10303b705cfSriastradh	XVMC_MPEG_2,
10403b705cfSriastradh	/* XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING, */
10503b705cfSriastradh	0,
10603b705cfSriastradh	/* &yv12_subpicture_list */
10703b705cfSriastradh	NULL,
10803b705cfSriastradh};
10903b705cfSriastradh
11003b705cfSriastradhstatic XF86MCSurfaceInfoRec i915_YV12_mpg1_surface = {
11103b705cfSriastradh	FOURCC_YV12,
11203b705cfSriastradh	XVMC_CHROMA_FORMAT_420,
11303b705cfSriastradh	0,
11403b705cfSriastradh	720,
11503b705cfSriastradh	576,
11603b705cfSriastradh	720,
11703b705cfSriastradh	576,
11803b705cfSriastradh	XVMC_MPEG_1,
11903b705cfSriastradh	/* XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING, */
12003b705cfSriastradh	0,
12103b705cfSriastradh	NULL,
12203b705cfSriastradh};
12303b705cfSriastradh
12403b705cfSriastradhstatic XF86MCSurfaceInfoPtr surface_info_i915[2] = {
12503b705cfSriastradh	(XF86MCSurfaceInfoPtr) & i915_YV12_mpg2_surface,
12603b705cfSriastradh	(XF86MCSurfaceInfoPtr) & i915_YV12_mpg1_surface
12703b705cfSriastradh};
12803b705cfSriastradh
12903b705cfSriastradh/* i965 and later hwmc support */
13003b705cfSriastradh#ifndef XVMC_VLD
13103b705cfSriastradh#define XVMC_VLD  0x00020000
13203b705cfSriastradh#endif
13303b705cfSriastradh
13403b705cfSriastradhstatic XF86MCSurfaceInfoRec yv12_mpeg2_vld_surface = {
13503b705cfSriastradh	FOURCC_YV12,
13603b705cfSriastradh	XVMC_CHROMA_FORMAT_420,
13703b705cfSriastradh	0,
13803b705cfSriastradh	1936,
13903b705cfSriastradh	1096,
14003b705cfSriastradh	1920,
14103b705cfSriastradh	1080,
14203b705cfSriastradh	XVMC_MPEG_2 | XVMC_VLD,
14303b705cfSriastradh	XVMC_INTRA_UNSIGNED,
14403b705cfSriastradh	NULL
14503b705cfSriastradh};
14603b705cfSriastradh
14703b705cfSriastradhstatic XF86MCSurfaceInfoRec yv12_mpeg2_i965_surface = {
14803b705cfSriastradh	FOURCC_YV12,
14903b705cfSriastradh	XVMC_CHROMA_FORMAT_420,
15003b705cfSriastradh	0,
15103b705cfSriastradh	1936,
15203b705cfSriastradh	1096,
15303b705cfSriastradh	1920,
15403b705cfSriastradh	1080,
15503b705cfSriastradh	XVMC_MPEG_2 | XVMC_MOCOMP,
15603b705cfSriastradh	/* XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING, */
15703b705cfSriastradh	XVMC_INTRA_UNSIGNED,
15803b705cfSriastradh	/* &yv12_subpicture_list */
15903b705cfSriastradh	NULL
16003b705cfSriastradh};
16103b705cfSriastradh
16203b705cfSriastradhstatic XF86MCSurfaceInfoRec yv12_mpeg1_i965_surface = {
16303b705cfSriastradh	FOURCC_YV12,
16403b705cfSriastradh	XVMC_CHROMA_FORMAT_420,
16503b705cfSriastradh	0,
16603b705cfSriastradh	1920,
16703b705cfSriastradh	1080,
16803b705cfSriastradh	1920,
16903b705cfSriastradh	1080,
17003b705cfSriastradh	XVMC_MPEG_1 | XVMC_MOCOMP,
17103b705cfSriastradh	/*XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING |
17203b705cfSriastradh	   XVMC_INTRA_UNSIGNED, */
17303b705cfSriastradh	XVMC_INTRA_UNSIGNED,
17403b705cfSriastradh
17503b705cfSriastradh	/*&yv12_subpicture_list */
17603b705cfSriastradh	NULL
17703b705cfSriastradh};
17803b705cfSriastradh
17903b705cfSriastradhstatic XF86MCSurfaceInfoPtr surface_info_i965[] = {
18003b705cfSriastradh	&yv12_mpeg2_i965_surface,
18103b705cfSriastradh	&yv12_mpeg1_i965_surface
18203b705cfSriastradh};
18303b705cfSriastradh
18403b705cfSriastradhstatic XF86MCSurfaceInfoPtr surface_info_vld[] = {
18503b705cfSriastradh	&yv12_mpeg2_vld_surface,
18603b705cfSriastradh	&yv12_mpeg2_i965_surface,
18703b705cfSriastradh};
18803b705cfSriastradh
18903b705cfSriastradh/* check chip type and load xvmc driver */
19003b705cfSriastradhBool intel_xvmc_adaptor_init(ScreenPtr pScreen)
19103b705cfSriastradh{
19203b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
19303b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
19413496ba1Ssnj	struct pci_device *pci;
19503b705cfSriastradh	static XF86MCAdaptorRec *pAdapt;
196fe8aea9eSmrg	const char *name;
19703b705cfSriastradh	char buf[64];
19803b705cfSriastradh
19903b705cfSriastradh	if (!intel->XvMCEnabled)
20003b705cfSriastradh		return FALSE;
20103b705cfSriastradh
20203b705cfSriastradh	/* Needs KMS support. */
20303b705cfSriastradh	if (IS_I915G(intel) || IS_I915GM(intel))
20403b705cfSriastradh		return FALSE;
20503b705cfSriastradh
20603b705cfSriastradh	if (IS_GEN2(intel)) {
20703b705cfSriastradh		ErrorF("Your chipset doesn't support XvMC.\n");
20803b705cfSriastradh		return FALSE;
20903b705cfSriastradh	}
21003b705cfSriastradh
21113496ba1Ssnj	pci = xf86GetPciInfoForEntity(intel->pEnt->index);
21213496ba1Ssnj	if (pci == NULL)
21313496ba1Ssnj		return FALSE;
21413496ba1Ssnj
21503b705cfSriastradh	pAdapt = calloc(1, sizeof(XF86MCAdaptorRec));
21603b705cfSriastradh	if (!pAdapt) {
21703b705cfSriastradh		ErrorF("Allocation error.\n");
21803b705cfSriastradh		return FALSE;
21903b705cfSriastradh	}
22003b705cfSriastradh
22103b705cfSriastradh	pAdapt->name = "Intel(R) Textured Video";
22203b705cfSriastradh	pAdapt->num_subpictures = 0;
22303b705cfSriastradh	pAdapt->subpictures = NULL;
22403b705cfSriastradh	pAdapt->CreateContext = create_context;
22503b705cfSriastradh	pAdapt->DestroyContext = destroy_context;
22603b705cfSriastradh	pAdapt->CreateSurface = create_surface;
22703b705cfSriastradh	pAdapt->DestroySurface = destroy_surface;
22803b705cfSriastradh	pAdapt->CreateSubpicture =  create_subpicture;
22903b705cfSriastradh	pAdapt->DestroySubpicture = destroy_subpicture;
23003b705cfSriastradh
23103b705cfSriastradh	if (IS_GEN3(intel)) {
23203b705cfSriastradh		name = "i915_xvmc",
23303b705cfSriastradh		pAdapt->num_surfaces = ARRAY_SIZE(surface_info_i915);
23403b705cfSriastradh		pAdapt->surfaces = surface_info_i915;
23503b705cfSriastradh	} else if (INTEL_INFO(intel)->gen >= 045) {
23603b705cfSriastradh		name = "xvmc_vld",
23703b705cfSriastradh		pAdapt->num_surfaces = ARRAY_SIZE(surface_info_vld);
23803b705cfSriastradh		pAdapt->surfaces = surface_info_vld;
23903b705cfSriastradh	} else {
24003b705cfSriastradh		name = "i965_xvmc",
24103b705cfSriastradh		pAdapt->num_surfaces = ARRAY_SIZE(surface_info_i965);
24203b705cfSriastradh		pAdapt->surfaces = surface_info_i965;
24303b705cfSriastradh	}
24403b705cfSriastradh
24503b705cfSriastradh	if (xf86XvMCScreenInit(pScreen, 1, &pAdapt)) {
24603b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_INFO,
24703b705cfSriastradh			   "[XvMC] %s driver initialized.\n",
24803b705cfSriastradh			   name);
24903b705cfSriastradh	} else {
25003b705cfSriastradh		intel->XvMCEnabled = FALSE;
25103b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_INFO,
25203b705cfSriastradh			   "[XvMC] Failed to initialize XvMC.\n");
25303b705cfSriastradh		return FALSE;
25403b705cfSriastradh	}
25503b705cfSriastradh
25603b705cfSriastradh	sprintf(buf, "pci:%04x:%02x:%02x.%d",
25713496ba1Ssnj		pci->domain, pci->bus, pci->dev, pci->func);
25803b705cfSriastradh
25903b705cfSriastradh	xf86XvMCRegisterDRInfo(pScreen, INTEL_XVMC_LIBNAME,
26003b705cfSriastradh			       buf,
26103b705cfSriastradh			       INTEL_XVMC_MAJOR, INTEL_XVMC_MINOR,
26203b705cfSriastradh			       INTEL_XVMC_PATCHLEVEL);
26303b705cfSriastradh	return TRUE;
26403b705cfSriastradh}
265