1fda9279dSmrg/*
2fda9279dSmrg * Copyright 2008 Ben Skeggs
3fda9279dSmrg *
4fda9279dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
5fda9279dSmrg * copy of this software and associated documentation files (the "Software"),
6fda9279dSmrg * to deal in the Software without restriction, including without limitation
7fda9279dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8fda9279dSmrg * and/or sell copies of the Software, and to permit persons to whom the
9fda9279dSmrg * Software is furnished to do so, subject to the following conditions:
10fda9279dSmrg *
11fda9279dSmrg * The above copyright notice and this permission notice shall be included in
12fda9279dSmrg * all copies or substantial portions of the Software.
13fda9279dSmrg *
14fda9279dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15fda9279dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16fda9279dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17fda9279dSmrg * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18fda9279dSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19fda9279dSmrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20fda9279dSmrg * SOFTWARE.
21fda9279dSmrg */
22fda9279dSmrg
23fda9279dSmrg#ifdef HAVE_CONFIG_H
24fda9279dSmrg#include "config.h"
25fda9279dSmrg#endif
26fda9279dSmrg
27479f40c1Smrg#include "xorg-config.h"
28fda9279dSmrg#include "xf86xv.h"
29fda9279dSmrg#include <X11/extensions/Xv.h>
30fda9279dSmrg#include "exa.h"
31fda9279dSmrg#include "damage.h"
32fda9279dSmrg#include "dixstruct.h"
33fda9279dSmrg#include "fourcc.h"
34fda9279dSmrg
35fda9279dSmrg#include "nv_include.h"
36fda9279dSmrg#include "nv_dma.h"
37fda9279dSmrg#include "nv50_accel.h"
38fda9279dSmrg
39fda9279dSmrgextern Atom xvSyncToVBlank, xvSetDefaults;
40fda9279dSmrgextern Atom xvBrightness, xvContrast, xvHue, xvSaturation;
41fda9279dSmrgextern Atom xvITURBT709;
42fda9279dSmrg
43fda9279dSmrgstatic Bool
44fda9279dSmrgnv50_xv_check_image_put(PixmapPtr ppix)
45fda9279dSmrg{
46fda9279dSmrg	switch (ppix->drawable.bitsPerPixel) {
47fda9279dSmrg	case 32:
48fda9279dSmrg	case 24:
49fda9279dSmrg	case 16:
50fda9279dSmrg	case 15:
51fda9279dSmrg		break;
52fda9279dSmrg	default:
53fda9279dSmrg		return FALSE;
54fda9279dSmrg	}
55fda9279dSmrg
56fda9279dSmrg	if (!nv50_style_tiled_pixmap(ppix))
57fda9279dSmrg		return FALSE;
58fda9279dSmrg
59fda9279dSmrg	return TRUE;
60fda9279dSmrg}
61fda9279dSmrg
62fda9279dSmrgint
63fda9279dSmrgnv50_xv_image_put(ScrnInfoPtr pScrn,
64fda9279dSmrg		  struct nouveau_bo *src, int packed_y, int uv,
65fda9279dSmrg		  int id, int src_pitch, BoxPtr dstBox,
66fda9279dSmrg		  int x1, int y1, int x2, int y2,
67fda9279dSmrg		  uint16_t width, uint16_t height,
68fda9279dSmrg		  uint16_t src_w, uint16_t src_h,
69fda9279dSmrg		  uint16_t drw_w, uint16_t drw_h,
70fda9279dSmrg		  RegionPtr clipBoxes, PixmapPtr ppix,
71fda9279dSmrg		  NVPortPrivPtr pPriv)
72fda9279dSmrg{
73fda9279dSmrg	NVPtr pNv = NVPTR(pScrn);
74fda9279dSmrg	struct nouveau_bo *dst = nouveau_pixmap_bo(ppix);
75fda9279dSmrg	struct nouveau_pushbuf *push = pNv->pushbuf;
76fda9279dSmrg	struct nouveau_pushbuf_refn refs[] = {
77fda9279dSmrg		{ pNv->scratch, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR },
78fda9279dSmrg		{ src, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD },
79fda9279dSmrg		{ dst, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR },
80fda9279dSmrg	};
81fda9279dSmrg	uint32_t mode = 0xd0005000 | (src->config.nv50.tile_mode << 18);
82fda9279dSmrg	float X1, X2, Y1, Y2;
83fda9279dSmrg	BoxPtr pbox;
84fda9279dSmrg	int nbox;
85fda9279dSmrg
86fda9279dSmrg	if (!nv50_xv_check_image_put(ppix))
87fda9279dSmrg		return BadMatch;
88fda9279dSmrg
89fda9279dSmrg	if (!PUSH_SPACE(push, 256))
90fda9279dSmrg		return BadImplementation;
91fda9279dSmrg
92fda9279dSmrg	BEGIN_NV04(push, NV50_3D(RT_ADDRESS_HIGH(0)), 5);
93fda9279dSmrg	PUSH_DATA (push, dst->offset >> 32);
94fda9279dSmrg	PUSH_DATA (push, dst->offset);
9522d74663Smrg	switch (ppix->drawable.depth) {
96fda9279dSmrg	case 32: PUSH_DATA (push, NV50_SURFACE_FORMAT_BGRA8_UNORM); break;
9722d74663Smrg	case 30: PUSH_DATA (push, NV50_SURFACE_FORMAT_RGB10_A2_UNORM); break;
98fda9279dSmrg	case 24: PUSH_DATA (push, NV50_SURFACE_FORMAT_BGRX8_UNORM); break;
99fda9279dSmrg	case 16: PUSH_DATA (push, NV50_SURFACE_FORMAT_B5G6R5_UNORM); break;
100fda9279dSmrg	case 15: PUSH_DATA (push, NV50_SURFACE_FORMAT_BGR5_X1_UNORM); break;
101fda9279dSmrg	}
102fda9279dSmrg	PUSH_DATA (push, dst->config.nv50.tile_mode);
103fda9279dSmrg	PUSH_DATA (push, 0);
104fda9279dSmrg	BEGIN_NV04(push, NV50_3D(RT_HORIZ(0)), 2);
105fda9279dSmrg	PUSH_DATA (push, ppix->drawable.width);
106fda9279dSmrg	PUSH_DATA (push, ppix->drawable.height);
107fda9279dSmrg	BEGIN_NV04(push, NV50_3D(RT_ARRAY_MODE), 1);
108fda9279dSmrg	PUSH_DATA (push, 1);
109fda9279dSmrg
110fda9279dSmrg	BEGIN_NV04(push, NV50_3D(BLEND_ENABLE(0)), 1);
111fda9279dSmrg	PUSH_DATA (push, 0);
112fda9279dSmrg
113fda9279dSmrg	PUSH_DATAu(push, pNv->scratch, TIC_OFFSET, 16);
114fda9279dSmrg	if (id == FOURCC_YV12 || id == FOURCC_I420) {
115fda9279dSmrg	PUSH_DATA (push, NV50TIC_0_0_MAPA_C0 | NV50TIC_0_0_TYPEA_UNORM |
116fda9279dSmrg			 NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM |
117fda9279dSmrg			 NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM |
118fda9279dSmrg			 NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM |
119fda9279dSmrg			 NV50TIC_0_0_FMT_8);
120fda9279dSmrg	PUSH_DATA (push, (src->offset + packed_y));
121fda9279dSmrg	PUSH_DATA (push, (src->offset + packed_y) >> 32 | mode);
122fda9279dSmrg	PUSH_DATA (push, 0x00300000);
123fda9279dSmrg	PUSH_DATA (push, width);
124fda9279dSmrg	PUSH_DATA (push, (1 << NV50TIC_0_5_DEPTH_SHIFT) | height);
125fda9279dSmrg	PUSH_DATA (push, 0x03000000);
126fda9279dSmrg	PUSH_DATA (push, 0x00000000);
127fda9279dSmrg	PUSH_DATA (push, NV50TIC_0_0_MAPA_C1 | NV50TIC_0_0_TYPEA_UNORM |
128fda9279dSmrg			 NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM |
129fda9279dSmrg			 NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM |
130fda9279dSmrg			 NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM |
131fda9279dSmrg			 NV50TIC_0_0_FMT_8_8);
132fda9279dSmrg	PUSH_DATA (push, (src->offset + uv));
133fda9279dSmrg	PUSH_DATA (push, (src->offset + uv) >> 32 | mode);
134fda9279dSmrg	PUSH_DATA (push, 0x00300000);
135fda9279dSmrg	PUSH_DATA (push, width >> 1);
136fda9279dSmrg	PUSH_DATA (push, (1 << NV50TIC_0_5_DEPTH_SHIFT) | (height >> 1));
137fda9279dSmrg	PUSH_DATA (push, 0x03000000);
138fda9279dSmrg	PUSH_DATA (push, 0x00000000);
139fda9279dSmrg	} else {
140fda9279dSmrg	if (id == FOURCC_UYVY) {
141fda9279dSmrg	PUSH_DATA (push, NV50TIC_0_0_MAPA_C1 | NV50TIC_0_0_TYPEA_UNORM |
142fda9279dSmrg			 NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM |
143fda9279dSmrg			 NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM |
144fda9279dSmrg			 NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM |
145fda9279dSmrg			 NV50TIC_0_0_FMT_8_8);
146fda9279dSmrg	} else {
147fda9279dSmrg	PUSH_DATA (push, NV50TIC_0_0_MAPA_C0 | NV50TIC_0_0_TYPEA_UNORM |
148fda9279dSmrg			 NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM |
149fda9279dSmrg			 NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM |
150fda9279dSmrg			 NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM |
151fda9279dSmrg			 NV50TIC_0_0_FMT_8_8);
152fda9279dSmrg	}
153fda9279dSmrg	PUSH_DATA (push, (src->offset + packed_y));
154fda9279dSmrg	PUSH_DATA (push, (src->offset + packed_y) >> 32 | mode);
155fda9279dSmrg	PUSH_DATA (push, 0x00300000);
156fda9279dSmrg	PUSH_DATA (push, width);
157fda9279dSmrg	PUSH_DATA (push, (1 << NV50TIC_0_5_DEPTH_SHIFT) | height);
158fda9279dSmrg	PUSH_DATA (push, 0x03000000);
159fda9279dSmrg	PUSH_DATA (push, 0x00000000);
160fda9279dSmrg	if (id == FOURCC_UYVY) {
161fda9279dSmrg	PUSH_DATA (push, NV50TIC_0_0_MAPA_C2 | NV50TIC_0_0_TYPEA_UNORM |
162fda9279dSmrg			 NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM |
163fda9279dSmrg			 NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM |
164fda9279dSmrg			 NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM |
165fda9279dSmrg			 NV50TIC_0_0_FMT_8_8_8_8);
166fda9279dSmrg	} else {
167fda9279dSmrg	PUSH_DATA (push, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM |
168fda9279dSmrg			 NV50TIC_0_0_MAPB_C1 | NV50TIC_0_0_TYPEB_UNORM |
169fda9279dSmrg			 NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM |
170fda9279dSmrg			 NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM |
171fda9279dSmrg			 NV50TIC_0_0_FMT_8_8_8_8);
172fda9279dSmrg	}
173fda9279dSmrg	PUSH_DATA (push, (src->offset + packed_y));
174fda9279dSmrg	PUSH_DATA (push, (src->offset + packed_y) >> 32 | mode);
175fda9279dSmrg	PUSH_DATA (push, 0x00300000);
176fda9279dSmrg	PUSH_DATA (push, (width >> 1));
177fda9279dSmrg	PUSH_DATA (push, (1 << NV50TIC_0_5_DEPTH_SHIFT) | height);
178fda9279dSmrg	PUSH_DATA (push, 0x03000000);
179fda9279dSmrg	PUSH_DATA (push, 0x00000000);
180fda9279dSmrg	}
181fda9279dSmrg
182fda9279dSmrg	PUSH_DATAu(push, pNv->scratch, TSC_OFFSET, 16);
183fda9279dSmrg	PUSH_DATA (push, NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE |
184fda9279dSmrg			 NV50TSC_1_0_WRAPT_CLAMP_TO_EDGE |
185fda9279dSmrg			 NV50TSC_1_0_WRAPR_CLAMP_TO_EDGE);
186fda9279dSmrg	PUSH_DATA (push, NV50TSC_1_1_MAGF_LINEAR |
187fda9279dSmrg			 NV50TSC_1_1_MINF_LINEAR |
188fda9279dSmrg			 NV50TSC_1_1_MIPF_NONE);
189fda9279dSmrg	PUSH_DATA (push, 0x00000000);
190fda9279dSmrg	PUSH_DATA (push, 0x00000000);
191fda9279dSmrg	PUSH_DATA (push, 0x00000000);
192fda9279dSmrg	PUSH_DATA (push, 0x00000000);
193fda9279dSmrg	PUSH_DATA (push, 0x00000000);
194fda9279dSmrg	PUSH_DATA (push, 0x00000000);
195fda9279dSmrg	PUSH_DATA (push, NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE |
196fda9279dSmrg			 NV50TSC_1_0_WRAPT_CLAMP_TO_EDGE |
197fda9279dSmrg			 NV50TSC_1_0_WRAPR_CLAMP_TO_EDGE);
198fda9279dSmrg	PUSH_DATA (push, NV50TSC_1_1_MAGF_LINEAR |
199fda9279dSmrg			 NV50TSC_1_1_MINF_LINEAR |
200fda9279dSmrg			 NV50TSC_1_1_MIPF_NONE);
201fda9279dSmrg	PUSH_DATA (push, 0x00000000);
202fda9279dSmrg	PUSH_DATA (push, 0x00000000);
203fda9279dSmrg	PUSH_DATA (push, 0x00000000);
204fda9279dSmrg	PUSH_DATA (push, 0x00000000);
205fda9279dSmrg	PUSH_DATA (push, 0x00000000);
206fda9279dSmrg	PUSH_DATA (push, 0x00000000);
207fda9279dSmrg
208fda9279dSmrg	BEGIN_NV04(push, NV50_3D(FP_START_ID), 1);
209fda9279dSmrg	PUSH_DATA (push, PFP_NV12);
210fda9279dSmrg
21116ee1e9aSmrg	BEGIN_NV04(push, NV50_3D(TIC_FLUSH), 1);
212fda9279dSmrg	PUSH_DATA (push, 0);
213fda9279dSmrg
214fda9279dSmrg	BEGIN_NV04(push, NV50_3D(BIND_TIC(2)), 1);
215fda9279dSmrg	PUSH_DATA (push, 1);
216fda9279dSmrg	BEGIN_NV04(push, NV50_3D(BIND_TIC(2)), 1);
217fda9279dSmrg	PUSH_DATA (push, 0x203);
218fda9279dSmrg
219fda9279dSmrg	PUSH_DATAu(push, pNv->scratch, PVP_DATA, 11);
220fda9279dSmrg	PUSH_DATAf(push, 1.0);
221fda9279dSmrg	PUSH_DATAf(push, 0.0);
222fda9279dSmrg	PUSH_DATAf(push, 0.0);
223fda9279dSmrg	PUSH_DATAf(push, 0.0);
224fda9279dSmrg	PUSH_DATAf(push, 1.0);
225fda9279dSmrg	PUSH_DATAf(push, 0.0);
226fda9279dSmrg	PUSH_DATAf(push, 0.0);
227fda9279dSmrg	PUSH_DATAf(push, 0.0);
228fda9279dSmrg	PUSH_DATAf(push, 1.0);
229fda9279dSmrg	PUSH_DATAf(push, 1.0 / width);
230fda9279dSmrg	PUSH_DATAf(push, 1.0 / height);
231fda9279dSmrg
232fda9279dSmrg	if (pPriv->SyncToVBlank)
233fda9279dSmrg		NV50SyncToVBlank(ppix, dstBox);
234fda9279dSmrg
235fda9279dSmrg	/* These are fixed point values in the 16.16 format. */
236fda9279dSmrg	X1 = (float)(x1>>16)+(float)(x1&0xFFFF)/(float)0x10000;
237fda9279dSmrg	Y1 = (float)(y1>>16)+(float)(y1&0xFFFF)/(float)0x10000;
238fda9279dSmrg	X2 = (float)(x2>>16)+(float)(x2&0xFFFF)/(float)0x10000;
239fda9279dSmrg	Y2 = (float)(y2>>16)+(float)(y2&0xFFFF)/(float)0x10000;
240fda9279dSmrg
241fda9279dSmrg	pbox = REGION_RECTS(clipBoxes);
242fda9279dSmrg	nbox = REGION_NUM_RECTS(clipBoxes);
243fda9279dSmrg	while(nbox--) {
244fda9279dSmrg		float tx1=X1+(float)(pbox->x1 - dstBox->x1)*(X2-X1)/(float)(drw_w);
245fda9279dSmrg		float tx2=X1+(float)(pbox->x2 - dstBox->x1)*(src_w)/(float)(drw_w);
246fda9279dSmrg		float ty1=Y1+(float)(pbox->y1 - dstBox->y1)*(Y2-Y1)/(float)(drw_h);
247fda9279dSmrg		float ty2=Y1+(float)(pbox->y2 - dstBox->y1)*(src_h)/(float)(drw_h);
248fda9279dSmrg		int sx1=pbox->x1;
249fda9279dSmrg		int sx2=pbox->x2;
250fda9279dSmrg		int sy1=pbox->y1;
251fda9279dSmrg		int sy2=pbox->y2;
252fda9279dSmrg
253fda9279dSmrg		if (nouveau_pushbuf_space(push, 64, 0, 0) ||
254fda9279dSmrg		    nouveau_pushbuf_refn (push, refs, 3))
255fda9279dSmrg			return BadImplementation;
256fda9279dSmrg
257fda9279dSmrg		/* NV50_3D_SCISSOR_VERT_T_SHIFT is wrong, because it was deducted with
258fda9279dSmrg		* origin lying at the bottom left. This will be changed to _MIN_ and _MAX_
259fda9279dSmrg		* later, because it is origin dependent.
260fda9279dSmrg		*/
261fda9279dSmrg		BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2);
262fda9279dSmrg		PUSH_DATA (push, sx2 << NV50_3D_SCISSOR_HORIZ_MAX__SHIFT | sx1);
263fda9279dSmrg		PUSH_DATA (push, sy2 << NV50_3D_SCISSOR_VERT_MAX__SHIFT | sy1 );
264fda9279dSmrg		BEGIN_NV04(push, NV50_3D(VERTEX_BEGIN_GL), 1);
265fda9279dSmrg		PUSH_DATA (push, NV50_3D_VERTEX_BEGIN_GL_PRIMITIVE_TRIANGLES);
266fda9279dSmrg		PUSH_VTX1s(push, tx1, ty1, sx1, sy1);
267fda9279dSmrg		PUSH_VTX1s(push, tx2+(tx2-tx1), ty1, sx2+(sx2-sx1), sy1);
268fda9279dSmrg		PUSH_VTX1s(push, tx1, ty2+(ty2-ty1), sx1, sy2+(sy2-sy1));
269fda9279dSmrg		BEGIN_NV04(push, NV50_3D(VERTEX_END_GL), 1);
270fda9279dSmrg		PUSH_DATA (push, 0);
271fda9279dSmrg
272fda9279dSmrg		pbox++;
273fda9279dSmrg	}
274fda9279dSmrg
275fda9279dSmrg	PUSH_KICK(push);
276fda9279dSmrg	return Success;
277fda9279dSmrg}
278fda9279dSmrg
279fda9279dSmrgvoid
280fda9279dSmrgnv50_xv_video_stop(ScrnInfoPtr pScrn, pointer data, Bool exit)
281fda9279dSmrg{
282fda9279dSmrg}
283fda9279dSmrg
284fda9279dSmrg/* Reference color space transform data */
285fda9279dSmrgstruct REF_TRANSFORM {
286fda9279dSmrg    float   RefLuma;
287fda9279dSmrg    float   RefRCb;
288fda9279dSmrg    float   RefRCr;
289fda9279dSmrg    float   RefGCb;
290fda9279dSmrg    float   RefGCr;
291fda9279dSmrg    float   RefBCb;
292fda9279dSmrg    float   RefBCr;
293fda9279dSmrg} trans[] = {
294fda9279dSmrg	{ 1.1643, 0.0, 1.5960, -0.3918, -0.8129, 2.0172, 0.0 }, /* BT.601 */
295fda9279dSmrg	{ 1.1643, 0.0, 1.7927, -0.2132, -0.5329, 2.1124, 0.0 }  /* BT.709 */
296fda9279dSmrg};
297fda9279dSmrg
298fda9279dSmrg#define RTFSaturation(a)   (1.0 + ((a)*1.0)/1000.0)
299fda9279dSmrg#define RTFBrightness(a)   (((a)*1.0)/2000.0)
300fda9279dSmrg#define RTFContrast(a)   (1.0 + ((a)*1.0)/1000.0)
301fda9279dSmrg#define RTFHue(a)   (((a)*3.1416)/1000.0)
302fda9279dSmrg
303fda9279dSmrgvoid
304fda9279dSmrgnv50_xv_csc_update(ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
305fda9279dSmrg{
306fda9279dSmrg	NVPtr pNv = NVPTR(pScrn);
307fda9279dSmrg	struct nouveau_pushbuf *push = pNv->pushbuf;
308fda9279dSmrg	const float Loff = -0.0627;
309fda9279dSmrg	const float Coff = -0.502;
310fda9279dSmrg	float yco, off[3], uco[3], vco[3];
311fda9279dSmrg	float uvcosf, uvsinf;
312fda9279dSmrg	float bright, cont;
313fda9279dSmrg	int ref = pPriv->iturbt_709;
314fda9279dSmrg
315fda9279dSmrg	cont = RTFContrast(pPriv->contrast);
316fda9279dSmrg	bright = RTFBrightness(pPriv->brightness);
317fda9279dSmrg	uvcosf = RTFSaturation(pPriv->saturation) * cos(RTFHue(pPriv->hue));
318fda9279dSmrg	uvsinf = RTFSaturation(pPriv->saturation) * sin(RTFHue(pPriv->hue));
319fda9279dSmrg
320fda9279dSmrg	yco = trans[ref].RefLuma * cont;
321fda9279dSmrg	uco[0] = -trans[ref].RefRCr * uvsinf;
322fda9279dSmrg	uco[1] = trans[ref].RefGCb * uvcosf - trans[ref].RefGCr * uvsinf;
323fda9279dSmrg	uco[2] = trans[ref].RefBCb * uvcosf;
324fda9279dSmrg	vco[0] = trans[ref].RefRCr * uvcosf;
325fda9279dSmrg	vco[1] = trans[ref].RefGCb * uvsinf + trans[ref].RefGCr * uvcosf;
326fda9279dSmrg	vco[2] = trans[ref].RefBCb * uvsinf;
327fda9279dSmrg	off[0] = Loff * yco + Coff * (uco[0] + vco[0]) + bright;
328fda9279dSmrg	off[1] = Loff * yco + Coff * (uco[1] + vco[1]) + bright;
329fda9279dSmrg	off[2] = Loff * yco + Coff * (uco[2] + vco[2]) + bright;
330fda9279dSmrg
331fda9279dSmrg	if (pNv->Architecture >= NV_FERMI) {
332fda9279dSmrg		nvc0_xv_csc_update(pNv, yco, off, uco, vco);
333fda9279dSmrg		return;
334fda9279dSmrg	}
335fda9279dSmrg
336fda9279dSmrg	if (nouveau_pushbuf_space(push, 64, 0, 0) ||
337fda9279dSmrg	    nouveau_pushbuf_refn (push, &(struct nouveau_pushbuf_refn) {
338fda9279dSmrg					pNv->scratch, NOUVEAU_BO_WR |
339fda9279dSmrg					NOUVEAU_BO_VRAM }, 1))
340fda9279dSmrg		return;
341fda9279dSmrg
342fda9279dSmrg	PUSH_DATAu(push, pNv->scratch, PFP_DATA, 10);
343fda9279dSmrg	PUSH_DATAf(push, yco);
344fda9279dSmrg	PUSH_DATAf(push, off[0]);
345fda9279dSmrg	PUSH_DATAf(push, off[1]);
346fda9279dSmrg	PUSH_DATAf(push, off[2]);
347fda9279dSmrg	PUSH_DATAf(push, uco[0]);
348fda9279dSmrg	PUSH_DATAf(push, uco[1]);
349fda9279dSmrg	PUSH_DATAf(push, uco[2]);
350fda9279dSmrg	PUSH_DATAf(push, vco[0]);
351fda9279dSmrg	PUSH_DATAf(push, vco[1]);
352fda9279dSmrg	PUSH_DATAf(push, vco[2]);
353fda9279dSmrg}
354fda9279dSmrg
355fda9279dSmrgvoid
356fda9279dSmrgnv50_xv_set_port_defaults(ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
357fda9279dSmrg{
358fda9279dSmrg	pPriv->videoStatus	= 0;
359fda9279dSmrg	pPriv->grabbedByV4L	= FALSE;
360fda9279dSmrg	pPriv->blitter		= FALSE;
361fda9279dSmrg	pPriv->texture		= TRUE;
362fda9279dSmrg	pPriv->doubleBuffer	= FALSE;
363fda9279dSmrg	pPriv->SyncToVBlank	= TRUE;
364fda9279dSmrg	pPriv->brightness	= 0;
365fda9279dSmrg	pPriv->contrast		= 0;
366fda9279dSmrg	pPriv->saturation	= 0;
367fda9279dSmrg	pPriv->hue		= 0;
368fda9279dSmrg	pPriv->iturbt_709	= 0;
36916ee1e9aSmrg	pPriv->max_image_dim    = 8192;
370fda9279dSmrg}
371fda9279dSmrg
372fda9279dSmrgint
373fda9279dSmrgnv50_xv_port_attribute_set(ScrnInfoPtr pScrn, Atom attribute,
374fda9279dSmrg			   INT32 value, pointer data)
375fda9279dSmrg{
376fda9279dSmrg	NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
377fda9279dSmrg
378fda9279dSmrg	if (attribute == xvSyncToVBlank) {
379fda9279dSmrg		if (value < 0 || value > 1)
380fda9279dSmrg			return BadValue;
381fda9279dSmrg		pPriv->SyncToVBlank = value;
382fda9279dSmrg	} else
383fda9279dSmrg	if (attribute == xvBrightness) {
384fda9279dSmrg		if (value < -1000 || value > 1000)
385fda9279dSmrg			return BadValue;
386fda9279dSmrg		pPriv->brightness = value;
387fda9279dSmrg	} else
388fda9279dSmrg	if (attribute == xvContrast) {
389fda9279dSmrg		if (value < -1000 || value > 1000)
390fda9279dSmrg			return BadValue;
391fda9279dSmrg		pPriv->contrast = value;
392fda9279dSmrg	} else
393fda9279dSmrg	if (attribute == xvSaturation) {
394fda9279dSmrg		if (value < -1000 || value > 1000)
395fda9279dSmrg			return BadValue;
396fda9279dSmrg		pPriv->saturation = value;
397fda9279dSmrg	} else
398fda9279dSmrg	if (attribute == xvHue) {
399fda9279dSmrg		if (value < -1000 || value > 1000)
400fda9279dSmrg			return BadValue;
401fda9279dSmrg		pPriv->hue = value;
402fda9279dSmrg	} else
403fda9279dSmrg	if (attribute == xvITURBT709) {
404fda9279dSmrg		if (value < 0 || value > 1)
405fda9279dSmrg			return BadValue;
406fda9279dSmrg		pPriv->iturbt_709 = value;
407fda9279dSmrg	} else
408fda9279dSmrg	if (attribute == xvSetDefaults) {
409fda9279dSmrg		nv50_xv_set_port_defaults(pScrn, pPriv);
410fda9279dSmrg	} else
411fda9279dSmrg		return BadMatch;
412fda9279dSmrg
413fda9279dSmrg	nv50_xv_csc_update(pScrn, pPriv);
414fda9279dSmrg	return Success;
415fda9279dSmrg}
416fda9279dSmrg
417fda9279dSmrgint
418fda9279dSmrgnv50_xv_port_attribute_get(ScrnInfoPtr pScrn, Atom attribute,
419fda9279dSmrg			   INT32 *value, pointer data)
420fda9279dSmrg{
421fda9279dSmrg	NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
422fda9279dSmrg
423fda9279dSmrg	if (attribute == xvSyncToVBlank)
424fda9279dSmrg		*value = (pPriv->SyncToVBlank) ? 1 : 0;
425fda9279dSmrg	else
426fda9279dSmrg	if (attribute == xvBrightness)
427fda9279dSmrg		*value = pPriv->brightness;
428fda9279dSmrg	else
429fda9279dSmrg	if (attribute == xvContrast)
430fda9279dSmrg		*value = pPriv->contrast;
431fda9279dSmrg	else
432fda9279dSmrg	if (attribute == xvSaturation)
433fda9279dSmrg		*value = pPriv->saturation;
434fda9279dSmrg	else
435fda9279dSmrg	if (attribute == xvHue)
436fda9279dSmrg		*value = pPriv->hue;
437fda9279dSmrg	else
438fda9279dSmrg	if (attribute == xvITURBT709)
439fda9279dSmrg		*value = pPriv->iturbt_709;
440fda9279dSmrg	else
441fda9279dSmrg		return BadMatch;
442fda9279dSmrg
443fda9279dSmrg	return Success;
444fda9279dSmrg}
445fda9279dSmrg
446fda9279dSmrg
447