1/*
2    yuv support
3
4    Copyright (C) 2007  Ian Armstrong <ian@iarmst.demon.co.uk>
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21#include "ivtv-driver.h"
22#include "ivtv-udma.h"
23#include "ivtv-yuv.h"
24
25/* YUV buffer offsets */
26const u32 yuv_offset[IVTV_YUV_BUFFERS] = {
27	0x001a8600,
28	0x00240400,
29	0x002d8200,
30	0x00370000,
31	0x00029000,
32	0x000C0E00,
33	0x006B0400,
34	0x00748200
35};
36
37static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
38				  struct ivtv_dma_frame *args)
39{
40	struct ivtv_dma_page_info y_dma;
41	struct ivtv_dma_page_info uv_dma;
42	struct yuv_playback_info *yi = &itv->yuv_info;
43	u8 frame = yi->draw_frame;
44	struct yuv_frame_info *f = &yi->new_frame_info[frame];
45	int i;
46	int y_pages, uv_pages;
47	unsigned long y_buffer_offset, uv_buffer_offset;
48	int y_decode_height, uv_decode_height, y_size;
49
50	y_buffer_offset = IVTV_DECODER_OFFSET + yuv_offset[frame];
51	uv_buffer_offset = y_buffer_offset + IVTV_YUV_BUFFER_UV_OFFSET;
52
53	y_decode_height = uv_decode_height = f->src_h + f->src_y;
54
55	if (f->offset_y)
56		y_buffer_offset += 720 * 16;
57
58	if (y_decode_height & 15)
59		y_decode_height = (y_decode_height + 16) & ~15;
60
61	if (uv_decode_height & 31)
62		uv_decode_height = (uv_decode_height + 32) & ~31;
63
64	y_size = 720 * y_decode_height;
65
66	/* Still in USE */
67	if (dma->SG_length || dma->page_count) {
68		IVTV_DEBUG_WARN
69		    ("prep_user_dma: SG_length %d page_count %d still full?\n",
70		     dma->SG_length, dma->page_count);
71		return -EBUSY;
72	}
73
74	ivtv_udma_get_page_info (&y_dma, (unsigned long)args->y_source, 720 * y_decode_height);
75	ivtv_udma_get_page_info (&uv_dma, (unsigned long)args->uv_source, 360 * uv_decode_height);
76
77	/* Get user pages for DMA Xfer */
78	y_pages = get_user_pages_unlocked(current, current->mm,
79				y_dma.uaddr, y_dma.page_count, 0, 1,
80				&dma->map[0]);
81	uv_pages = 0; /* silence gcc. value is set and consumed only if: */
82	if (y_pages == y_dma.page_count) {
83		uv_pages = get_user_pages_unlocked(current, current->mm,
84					uv_dma.uaddr, uv_dma.page_count, 0, 1,
85					&dma->map[y_pages]);
86	}
87
88	if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) {
89		int rc = -EFAULT;
90
91		if (y_pages == y_dma.page_count) {
92			IVTV_DEBUG_WARN
93				("failed to map uv user pages, returned %d "
94				 "expecting %d\n", uv_pages, uv_dma.page_count);
95
96			if (uv_pages >= 0) {
97				for (i = 0; i < uv_pages; i++)
98					put_page(dma->map[y_pages + i]);
99				rc = -EFAULT;
100			} else {
101				rc = uv_pages;
102			}
103		} else {
104			IVTV_DEBUG_WARN
105				("failed to map y user pages, returned %d "
106				 "expecting %d\n", y_pages, y_dma.page_count);
107		}
108		if (y_pages >= 0) {
109			for (i = 0; i < y_pages; i++)
110				put_page(dma->map[i]);
111			/*
112			 * Inherit the -EFAULT from rc's
113			 * initialization, but allow it to be
114			 * overriden by uv_pages above if it was an
115			 * actual errno.
116			 */
117		} else {
118			rc = y_pages;
119		}
120		return rc;
121	}
122
123	dma->page_count = y_pages + uv_pages;
124
125	/* Fill & map SG List */
126	if (ivtv_udma_fill_sg_list (dma, &uv_dma, ivtv_udma_fill_sg_list (dma, &y_dma, 0)) < 0) {
127		IVTV_DEBUG_WARN("could not allocate bounce buffers for highmem userspace buffers\n");
128		for (i = 0; i < dma->page_count; i++) {
129			put_page(dma->map[i]);
130		}
131		dma->page_count = 0;
132		return -ENOMEM;
133	}
134	dma->SG_length = pci_map_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE);
135
136	/* Fill SG Array with new values */
137	ivtv_udma_fill_sg_array(dma, y_buffer_offset, uv_buffer_offset, y_size);
138
139	/* If we've offset the y plane, ensure top area is blanked */
140	if (f->offset_y && yi->blanking_dmaptr) {
141		dma->SGarray[dma->SG_length].size = cpu_to_le32(720*16);
142		dma->SGarray[dma->SG_length].src = cpu_to_le32(yi->blanking_dmaptr);
143		dma->SGarray[dma->SG_length].dst = cpu_to_le32(IVTV_DECODER_OFFSET + yuv_offset[frame]);
144		dma->SG_length++;
145	}
146
147	/* Tag SG Array with Interrupt Bit */
148	dma->SGarray[dma->SG_length - 1].size |= cpu_to_le32(0x80000000);
149
150	ivtv_udma_sync_for_device(itv);
151	return 0;
152}
153
154/* We rely on a table held in the firmware - Quick check. */
155int ivtv_yuv_filter_check(struct ivtv *itv)
156{
157	int i, y, uv;
158
159	for (i = 0, y = 16, uv = 4; i < 16; i++, y += 24, uv += 12) {
160		if ((read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + y) != i << 16) ||
161		    (read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET + uv) != i << 16)) {
162			IVTV_WARN ("YUV filter table not found in firmware.\n");
163			return -1;
164		}
165	}
166	return 0;
167}
168
169static void ivtv_yuv_filter(struct ivtv *itv, int h_filter, int v_filter_1, int v_filter_2)
170{
171	u32 i, line;
172
173	/* If any filter is -1, then don't update it */
174	if (h_filter > -1) {
175		if (h_filter > 4)
176			h_filter = 4;
177		i = IVTV_YUV_HORIZONTAL_FILTER_OFFSET + (h_filter * 384);
178		for (line = 0; line < 16; line++) {
179			write_reg(read_dec(i), 0x02804);
180			write_reg(read_dec(i), 0x0281c);
181			i += 4;
182			write_reg(read_dec(i), 0x02808);
183			write_reg(read_dec(i), 0x02820);
184			i += 4;
185			write_reg(read_dec(i), 0x0280c);
186			write_reg(read_dec(i), 0x02824);
187			i += 4;
188			write_reg(read_dec(i), 0x02810);
189			write_reg(read_dec(i), 0x02828);
190			i += 4;
191			write_reg(read_dec(i), 0x02814);
192			write_reg(read_dec(i), 0x0282c);
193			i += 8;
194			write_reg(0, 0x02818);
195			write_reg(0, 0x02830);
196		}
197		IVTV_DEBUG_YUV("h_filter -> %d\n", h_filter);
198	}
199
200	if (v_filter_1 > -1) {
201		if (v_filter_1 > 4)
202			v_filter_1 = 4;
203		i = IVTV_YUV_VERTICAL_FILTER_OFFSET + (v_filter_1 * 192);
204		for (line = 0; line < 16; line++) {
205			write_reg(read_dec(i), 0x02900);
206			i += 4;
207			write_reg(read_dec(i), 0x02904);
208			i += 8;
209			write_reg(0, 0x02908);
210		}
211		IVTV_DEBUG_YUV("v_filter_1 -> %d\n", v_filter_1);
212	}
213
214	if (v_filter_2 > -1) {
215		if (v_filter_2 > 4)
216			v_filter_2 = 4;
217		i = IVTV_YUV_VERTICAL_FILTER_OFFSET + (v_filter_2 * 192);
218		for (line = 0; line < 16; line++) {
219			write_reg(read_dec(i), 0x0290c);
220			i += 4;
221			write_reg(read_dec(i), 0x02910);
222			i += 8;
223			write_reg(0, 0x02914);
224		}
225		IVTV_DEBUG_YUV("v_filter_2 -> %d\n", v_filter_2);
226	}
227}
228
229static void ivtv_yuv_handle_horizontal(struct ivtv *itv, struct yuv_frame_info *f)
230{
231	struct yuv_playback_info *yi = &itv->yuv_info;
232	u32 reg_2834, reg_2838, reg_283c;
233	u32 reg_2844, reg_2854, reg_285c;
234	u32 reg_2864, reg_2874, reg_2890;
235	u32 reg_2870, reg_2870_base, reg_2870_offset;
236	int x_cutoff;
237	int h_filter;
238	u32 master_width;
239
240	IVTV_DEBUG_WARN
241	    ("Adjust to width %d src_w %d dst_w %d src_x %d dst_x %d\n",
242	     f->tru_w, f->src_w, f->dst_w, f->src_x, f->dst_x);
243
244	/* How wide is the src image */
245	x_cutoff = f->src_w + f->src_x;
246
247	/* Set the display width */
248	reg_2834 = f->dst_w;
249	reg_2838 = reg_2834;
250
251	/* Set the display position */
252	reg_2890 = f->dst_x;
253
254	/* Index into the image horizontally */
255	reg_2870 = 0;
256
257	/* 2870 is normally fudged to align video coords with osd coords.
258	   If running full screen, it causes an unwanted left shift
259	   Remove the fudge if we almost fill the screen.
260	   Gradually adjust the offset to avoid the video 'snapping'
261	   left/right if it gets dragged through this region.
262	   Only do this if osd is full width. */
263	if (f->vis_w == 720) {
264		if ((f->tru_x - f->pan_x > -1) && (f->tru_x - f->pan_x <= 40) && (f->dst_w >= 680))
265			reg_2870 = 10 - (f->tru_x - f->pan_x) / 4;
266		else if ((f->tru_x - f->pan_x < 0) && (f->tru_x - f->pan_x >= -20) && (f->dst_w >= 660))
267			reg_2870 = (10 + (f->tru_x - f->pan_x) / 2);
268
269		if (f->dst_w >= f->src_w)
270			reg_2870 = reg_2870 << 16 | reg_2870;
271		else
272			reg_2870 = ((reg_2870 & ~1) << 15) | (reg_2870 & ~1);
273	}
274
275	if (f->dst_w < f->src_w)
276		reg_2870 = 0x000d000e - reg_2870;
277	else
278		reg_2870 = 0x0012000e - reg_2870;
279
280	/* We're also using 2870 to shift the image left (src_x & negative dst_x) */
281	reg_2870_offset = (f->src_x * ((f->dst_w << 21) / f->src_w)) >> 19;
282
283	if (f->dst_w >= f->src_w) {
284		x_cutoff &= ~1;
285		master_width = (f->src_w * 0x00200000) / (f->dst_w);
286		if (master_width * f->dst_w != f->src_w * 0x00200000)
287			master_width++;
288		reg_2834 = (reg_2834 << 16) | x_cutoff;
289		reg_2838 = (reg_2838 << 16) | x_cutoff;
290		reg_283c = master_width >> 2;
291		reg_2844 = master_width >> 2;
292		reg_2854 = master_width;
293		reg_285c = master_width >> 1;
294		reg_2864 = master_width >> 1;
295
296		/* We also need to factor in the scaling
297		   (src_w - dst_w) / (src_w / 4) */
298		if (f->dst_w > f->src_w)
299			reg_2870_base = ((f->dst_w - f->src_w)<<16) / (f->src_w <<14);
300		else
301			reg_2870_base = 0;
302
303		reg_2870 += (((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 2) + (reg_2870_base << 17 | reg_2870_base);
304		reg_2874 = 0;
305	} else if (f->dst_w < f->src_w / 2) {
306		master_width = (f->src_w * 0x00080000) / f->dst_w;
307		if (master_width * f->dst_w != f->src_w * 0x00080000)
308			master_width++;
309		reg_2834 = (reg_2834 << 16) | x_cutoff;
310		reg_2838 = (reg_2838 << 16) | x_cutoff;
311		reg_283c = master_width >> 2;
312		reg_2844 = master_width >> 1;
313		reg_2854 = master_width;
314		reg_285c = master_width >> 1;
315		reg_2864 = master_width >> 1;
316		reg_2870 += ((reg_2870_offset << 15) & 0xFFFF0000) | reg_2870_offset;
317		reg_2870 += (5 - (((f->src_w + f->src_w / 2) - 1) / f->dst_w)) << 16;
318		reg_2874 = 0x00000012;
319	} else {
320		master_width = (f->src_w * 0x00100000) / f->dst_w;
321		if (master_width * f->dst_w != f->src_w * 0x00100000)
322			master_width++;
323		reg_2834 = (reg_2834 << 16) | x_cutoff;
324		reg_2838 = (reg_2838 << 16) | x_cutoff;
325		reg_283c = master_width >> 2;
326		reg_2844 = master_width >> 1;
327		reg_2854 = master_width;
328		reg_285c = master_width >> 1;
329		reg_2864 = master_width >> 1;
330		reg_2870 += ((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 1;
331		reg_2870 += (5 - (((f->src_w * 3) - 1) / f->dst_w)) << 16;
332		reg_2874 = 0x00000001;
333	}
334
335	/* Select the horizontal filter */
336	if (f->src_w == f->dst_w) {
337		/* An exact size match uses filter 0 */
338		h_filter = 0;
339	} else {
340		/* Figure out which filter to use */
341		h_filter = ((f->src_w << 16) / f->dst_w) >> 15;
342		h_filter = (h_filter >> 1) + (h_filter & 1);
343		/* Only an exact size match can use filter 0 */
344		h_filter += !h_filter;
345	}
346
347	write_reg(reg_2834, 0x02834);
348	write_reg(reg_2838, 0x02838);
349	IVTV_DEBUG_YUV("Update reg 0x2834 %08x->%08x 0x2838 %08x->%08x\n",
350		       yi->reg_2834, reg_2834, yi->reg_2838, reg_2838);
351
352	write_reg(reg_283c, 0x0283c);
353	write_reg(reg_2844, 0x02844);
354
355	IVTV_DEBUG_YUV("Update reg 0x283c %08x->%08x 0x2844 %08x->%08x\n",
356		       yi->reg_283c, reg_283c, yi->reg_2844, reg_2844);
357
358	write_reg(0x00080514, 0x02840);
359	write_reg(0x00100514, 0x02848);
360	IVTV_DEBUG_YUV("Update reg 0x2840 %08x->%08x 0x2848 %08x->%08x\n",
361		       yi->reg_2840, 0x00080514, yi->reg_2848, 0x00100514);
362
363	write_reg(reg_2854, 0x02854);
364	IVTV_DEBUG_YUV("Update reg 0x2854 %08x->%08x \n",
365		       yi->reg_2854, reg_2854);
366
367	write_reg(reg_285c, 0x0285c);
368	write_reg(reg_2864, 0x02864);
369	IVTV_DEBUG_YUV("Update reg 0x285c %08x->%08x 0x2864 %08x->%08x\n",
370		       yi->reg_285c, reg_285c, yi->reg_2864, reg_2864);
371
372	write_reg(reg_2874, 0x02874);
373	IVTV_DEBUG_YUV("Update reg 0x2874 %08x->%08x\n",
374		       yi->reg_2874, reg_2874);
375
376	write_reg(reg_2870, 0x02870);
377	IVTV_DEBUG_YUV("Update reg 0x2870 %08x->%08x\n",
378		       yi->reg_2870, reg_2870);
379
380	write_reg(reg_2890, 0x02890);
381	IVTV_DEBUG_YUV("Update reg 0x2890 %08x->%08x\n",
382		       yi->reg_2890, reg_2890);
383
384	/* Only update the filter if we really need to */
385	if (h_filter != yi->h_filter) {
386		ivtv_yuv_filter(itv, h_filter, -1, -1);
387		yi->h_filter = h_filter;
388	}
389}
390
391static void ivtv_yuv_handle_vertical(struct ivtv *itv, struct yuv_frame_info *f)
392{
393	struct yuv_playback_info *yi = &itv->yuv_info;
394	u32 master_height;
395	u32 reg_2918, reg_291c, reg_2920, reg_2928;
396	u32 reg_2930, reg_2934, reg_293c;
397	u32 reg_2940, reg_2944, reg_294c;
398	u32 reg_2950, reg_2954, reg_2958, reg_295c;
399	u32 reg_2960, reg_2964, reg_2968, reg_296c;
400	u32 reg_289c;
401	u32 src_major_y, src_minor_y;
402	u32 src_major_uv, src_minor_uv;
403	u32 reg_2964_base, reg_2968_base;
404	int v_filter_1, v_filter_2;
405
406	IVTV_DEBUG_WARN
407	    ("Adjust to height %d src_h %d dst_h %d src_y %d dst_y %d\n",
408	     f->tru_h, f->src_h, f->dst_h, f->src_y, f->dst_y);
409
410	/* What scaling mode is being used... */
411	IVTV_DEBUG_YUV("Scaling mode Y: %s\n",
412		       f->interlaced_y ? "Interlaced" : "Progressive");
413
414	IVTV_DEBUG_YUV("Scaling mode UV: %s\n",
415		       f->interlaced_uv ? "Interlaced" : "Progressive");
416
417	/* What is the source video being treated as... */
418	IVTV_DEBUG_WARN("Source video: %s\n",
419			f->interlaced ? "Interlaced" : "Progressive");
420
421	/* We offset into the image using two different index methods, so split
422	   the y source coord into two parts. */
423	if (f->src_y < 8) {
424		src_minor_uv = f->src_y;
425		src_major_uv = 0;
426	} else {
427		src_minor_uv = 8;
428		src_major_uv = f->src_y - 8;
429	}
430
431	src_minor_y = src_minor_uv;
432	src_major_y = src_major_uv;
433
434	if (f->offset_y)
435		src_minor_y += 16;
436
437	if (f->interlaced_y)
438		reg_2918 = (f->dst_h << 16) | (f->src_h + src_minor_y);
439	else
440		reg_2918 = (f->dst_h << 16) | ((f->src_h + src_minor_y) << 1);
441
442	if (f->interlaced_uv)
443		reg_291c = (f->dst_h << 16) | ((f->src_h + src_minor_uv) >> 1);
444	else
445		reg_291c = (f->dst_h << 16) | (f->src_h + src_minor_uv);
446
447	reg_2964_base = (src_minor_y * ((f->dst_h << 16) / f->src_h)) >> 14;
448	reg_2968_base = (src_minor_uv * ((f->dst_h << 16) / f->src_h)) >> 14;
449
450	if (f->dst_h / 2 >= f->src_h && !f->interlaced_y) {
451		master_height = (f->src_h * 0x00400000) / f->dst_h;
452		if ((f->src_h * 0x00400000) - (master_height * f->dst_h) >= f->dst_h / 2)
453			master_height++;
454		reg_2920 = master_height >> 2;
455		reg_2928 = master_height >> 3;
456		reg_2930 = master_height;
457		reg_2940 = master_height >> 1;
458		reg_2964_base >>= 3;
459		reg_2968_base >>= 3;
460		reg_296c = 0x00000000;
461	} else if (f->dst_h >= f->src_h) {
462		master_height = (f->src_h * 0x00400000) / f->dst_h;
463		master_height = (master_height >> 1) + (master_height & 1);
464		reg_2920 = master_height >> 2;
465		reg_2928 = master_height >> 2;
466		reg_2930 = master_height;
467		reg_2940 = master_height >> 1;
468		reg_296c = 0x00000000;
469		if (f->interlaced_y) {
470			reg_2964_base >>= 3;
471		} else {
472			reg_296c++;
473			reg_2964_base >>= 2;
474		}
475		if (f->interlaced_uv)
476			reg_2928 >>= 1;
477		reg_2968_base >>= 3;
478	} else if (f->dst_h >= f->src_h / 2) {
479		master_height = (f->src_h * 0x00200000) / f->dst_h;
480		master_height = (master_height >> 1) + (master_height & 1);
481		reg_2920 = master_height >> 2;
482		reg_2928 = master_height >> 2;
483		reg_2930 = master_height;
484		reg_2940 = master_height;
485		reg_296c = 0x00000101;
486		if (f->interlaced_y) {
487			reg_2964_base >>= 2;
488		} else {
489			reg_296c++;
490			reg_2964_base >>= 1;
491		}
492		if (f->interlaced_uv)
493			reg_2928 >>= 1;
494		reg_2968_base >>= 2;
495	} else {
496		master_height = (f->src_h * 0x00100000) / f->dst_h;
497		master_height = (master_height >> 1) + (master_height & 1);
498		reg_2920 = master_height >> 2;
499		reg_2928 = master_height >> 2;
500		reg_2930 = master_height;
501		reg_2940 = master_height;
502		reg_2964_base >>= 1;
503		reg_2968_base >>= 2;
504		reg_296c = 0x00000102;
505	}
506
507	/* FIXME These registers change depending on scaled / unscaled output
508	   We really need to work out what they should be */
509	if (f->src_h == f->dst_h) {
510		reg_2934 = 0x00020000;
511		reg_293c = 0x00100000;
512		reg_2944 = 0x00040000;
513		reg_294c = 0x000b0000;
514	} else {
515		reg_2934 = 0x00000FF0;
516		reg_293c = 0x00000FF0;
517		reg_2944 = 0x00000FF0;
518		reg_294c = 0x00000FF0;
519	}
520
521	/* The first line to be displayed */
522	reg_2950 = 0x00010000 + src_major_y;
523	if (f->interlaced_y)
524		reg_2950 += 0x00010000;
525	reg_2954 = reg_2950 + 1;
526
527	reg_2958 = 0x00010000 + (src_major_y >> 1);
528	if (f->interlaced_uv)
529		reg_2958 += 0x00010000;
530	reg_295c = reg_2958 + 1;
531
532	if (yi->decode_height == 480)
533		reg_289c = 0x011e0017;
534	else
535		reg_289c = 0x01500017;
536
537	if (f->dst_y < 0)
538		reg_289c = (reg_289c - ((f->dst_y & ~1)<<15))-(f->dst_y >>1);
539	else
540		reg_289c = (reg_289c + ((f->dst_y & ~1)<<15))+(f->dst_y >>1);
541
542	/* How much of the source to decode.
543	   Take into account the source offset */
544	reg_2960 = ((src_minor_y + f->src_h + src_major_y) - 1) |
545		(((src_minor_uv + f->src_h + src_major_uv - 1) & ~1) << 15);
546
547	/* Calculate correct value for register 2964 */
548	if (f->src_h == f->dst_h) {
549		reg_2964 = 1;
550	} else {
551		reg_2964 = 2 + ((f->dst_h << 1) / f->src_h);
552		reg_2964 = (reg_2964 >> 1) + (reg_2964 & 1);
553	}
554	reg_2968 = (reg_2964 << 16) + reg_2964 + (reg_2964 >> 1);
555	reg_2964 = (reg_2964 << 16) + reg_2964 + (reg_2964 * 46 / 94);
556
557	/* Okay, we've wasted time working out the correct value,
558	   but if we use it, it fouls the the window alignment.
559	   Fudge it to what we want... */
560	reg_2964 = 0x00010001 + ((reg_2964 & 0x0000FFFF) - (reg_2964 >> 16));
561	reg_2968 = 0x00010001 + ((reg_2968 & 0x0000FFFF) - (reg_2968 >> 16));
562
563	/* Deviate further from what it should be. I find the flicker headache
564	   inducing so try to reduce it slightly. Leave 2968 as-is otherwise
565	   colours foul. */
566	if ((reg_2964 != 0x00010001) && (f->dst_h / 2 <= f->src_h))
567		reg_2964 = (reg_2964 & 0xFFFF0000) + ((reg_2964 & 0x0000FFFF) / 2);
568
569	if (!f->interlaced_y)
570		reg_2964 -= 0x00010001;
571	if (!f->interlaced_uv)
572		reg_2968 -= 0x00010001;
573
574	reg_2964 += ((reg_2964_base << 16) | reg_2964_base);
575	reg_2968 += ((reg_2968_base << 16) | reg_2968_base);
576
577	/* Select the vertical filter */
578	if (f->src_h == f->dst_h) {
579		/* An exact size match uses filter 0/1 */
580		v_filter_1 = 0;
581		v_filter_2 = 1;
582	} else {
583		/* Figure out which filter to use */
584		v_filter_1 = ((f->src_h << 16) / f->dst_h) >> 15;
585		v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1);
586		/* Only an exact size match can use filter 0 */
587		v_filter_1 += !v_filter_1;
588		v_filter_2 = v_filter_1;
589	}
590
591	write_reg(reg_2934, 0x02934);
592	write_reg(reg_293c, 0x0293c);
593	IVTV_DEBUG_YUV("Update reg 0x2934 %08x->%08x 0x293c %08x->%08x\n",
594		       yi->reg_2934, reg_2934, yi->reg_293c, reg_293c);
595	write_reg(reg_2944, 0x02944);
596	write_reg(reg_294c, 0x0294c);
597	IVTV_DEBUG_YUV("Update reg 0x2944 %08x->%08x 0x294c %08x->%08x\n",
598		       yi->reg_2944, reg_2944, yi->reg_294c, reg_294c);
599
600	/* Ensure 2970 is 0 (does it ever change ?) */
601/*	write_reg(0,0x02970); */
602/*	IVTV_DEBUG_YUV("Update reg 0x2970 %08x->%08x\n", yi->reg_2970, 0); */
603
604	write_reg(reg_2930, 0x02938);
605	write_reg(reg_2930, 0x02930);
606	IVTV_DEBUG_YUV("Update reg 0x2930 %08x->%08x 0x2938 %08x->%08x\n",
607		       yi->reg_2930, reg_2930, yi->reg_2938, reg_2930);
608
609	write_reg(reg_2928, 0x02928);
610	write_reg(reg_2928 + 0x514, 0x0292C);
611	IVTV_DEBUG_YUV("Update reg 0x2928 %08x->%08x 0x292c %08x->%08x\n",
612		       yi->reg_2928, reg_2928, yi->reg_292c, reg_2928 + 0x514);
613
614	write_reg(reg_2920, 0x02920);
615	write_reg(reg_2920 + 0x514, 0x02924);
616	IVTV_DEBUG_YUV("Update reg 0x2920 %08x->%08x 0x2924 %08x->%08x\n",
617		       yi->reg_2920, reg_2920, yi->reg_2924, reg_2920 + 0x514);
618
619	write_reg(reg_2918, 0x02918);
620	write_reg(reg_291c, 0x0291C);
621	IVTV_DEBUG_YUV("Update reg 0x2918 %08x->%08x 0x291C %08x->%08x\n",
622		       yi->reg_2918, reg_2918, yi->reg_291c, reg_291c);
623
624	write_reg(reg_296c, 0x0296c);
625	IVTV_DEBUG_YUV("Update reg 0x296c %08x->%08x\n",
626		       yi->reg_296c, reg_296c);
627
628	write_reg(reg_2940, 0x02948);
629	write_reg(reg_2940, 0x02940);
630	IVTV_DEBUG_YUV("Update reg 0x2940 %08x->%08x 0x2948 %08x->%08x\n",
631		       yi->reg_2940, reg_2940, yi->reg_2948, reg_2940);
632
633	write_reg(reg_2950, 0x02950);
634	write_reg(reg_2954, 0x02954);
635	IVTV_DEBUG_YUV("Update reg 0x2950 %08x->%08x 0x2954 %08x->%08x\n",
636		       yi->reg_2950, reg_2950, yi->reg_2954, reg_2954);
637
638	write_reg(reg_2958, 0x02958);
639	write_reg(reg_295c, 0x0295C);
640	IVTV_DEBUG_YUV("Update reg 0x2958 %08x->%08x 0x295C %08x->%08x\n",
641		       yi->reg_2958, reg_2958, yi->reg_295c, reg_295c);
642
643	write_reg(reg_2960, 0x02960);
644	IVTV_DEBUG_YUV("Update reg 0x2960 %08x->%08x \n",
645		       yi->reg_2960, reg_2960);
646
647	write_reg(reg_2964, 0x02964);
648	write_reg(reg_2968, 0x02968);
649	IVTV_DEBUG_YUV("Update reg 0x2964 %08x->%08x 0x2968 %08x->%08x\n",
650		       yi->reg_2964, reg_2964, yi->reg_2968, reg_2968);
651
652	write_reg(reg_289c, 0x0289c);
653	IVTV_DEBUG_YUV("Update reg 0x289c %08x->%08x\n",
654		       yi->reg_289c, reg_289c);
655
656	/* Only update filter 1 if we really need to */
657	if (v_filter_1 != yi->v_filter_1) {
658		ivtv_yuv_filter(itv, -1, v_filter_1, -1);
659		yi->v_filter_1 = v_filter_1;
660	}
661
662	/* Only update filter 2 if we really need to */
663	if (v_filter_2 != yi->v_filter_2) {
664		ivtv_yuv_filter(itv, -1, -1, v_filter_2);
665		yi->v_filter_2 = v_filter_2;
666	}
667}
668
669/* Modify the supplied coordinate information to fit the visible osd area */
670static u32 ivtv_yuv_window_setup(struct ivtv *itv, struct yuv_frame_info *f)
671{
672	struct yuv_frame_info *of = &itv->yuv_info.old_frame_info;
673	int osd_crop;
674	u32 osd_scale;
675	u32 yuv_update = 0;
676
677	/* Sorry, but no negative coords for src */
678	if (f->src_x < 0)
679		f->src_x = 0;
680	if (f->src_y < 0)
681		f->src_y = 0;
682
683	/* Can only reduce width down to 1/4 original size */
684	if ((osd_crop = f->src_w - 4 * f->dst_w) > 0) {
685		f->src_x += osd_crop / 2;
686		f->src_w = (f->src_w - osd_crop) & ~3;
687		f->dst_w = f->src_w / 4;
688		f->dst_w += f->dst_w & 1;
689	}
690
691	/* Can only reduce height down to 1/4 original size */
692	if (f->src_h / f->dst_h >= 2) {
693		/* Overflow may be because we're running progressive,
694		   so force mode switch */
695		f->interlaced_y = 1;
696		/* Make sure we're still within limits for interlace */
697		if ((osd_crop = f->src_h - 4 * f->dst_h) > 0) {
698			/* If we reach here we'll have to force the height. */
699			f->src_y += osd_crop / 2;
700			f->src_h = (f->src_h - osd_crop) & ~3;
701			f->dst_h = f->src_h / 4;
702			f->dst_h += f->dst_h & 1;
703		}
704	}
705
706	/* If there's nothing to safe to display, we may as well stop now */
707	if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 ||
708	    (int)f->src_w <= 2 || (int)f->src_h <= 2) {
709		return IVTV_YUV_UPDATE_INVALID;
710	}
711
712	/* Ensure video remains inside OSD area */
713	osd_scale = (f->src_h << 16) / f->dst_h;
714
715	if ((osd_crop = f->pan_y - f->dst_y) > 0) {
716		/* Falls off the upper edge - crop */
717		f->src_y += (osd_scale * osd_crop) >> 16;
718		f->src_h -= (osd_scale * osd_crop) >> 16;
719		f->dst_h -= osd_crop;
720		f->dst_y = 0;
721	} else {
722		f->dst_y -= f->pan_y;
723	}
724
725	if ((osd_crop = f->dst_h + f->dst_y - f->vis_h) > 0) {
726		/* Falls off the lower edge - crop */
727		f->dst_h -= osd_crop;
728		f->src_h -= (osd_scale * osd_crop) >> 16;
729	}
730
731	osd_scale = (f->src_w << 16) / f->dst_w;
732
733	if ((osd_crop = f->pan_x - f->dst_x) > 0) {
734		/* Fall off the left edge - crop */
735		f->src_x += (osd_scale * osd_crop) >> 16;
736		f->src_w -= (osd_scale * osd_crop) >> 16;
737		f->dst_w -= osd_crop;
738		f->dst_x = 0;
739	} else {
740		f->dst_x -= f->pan_x;
741	}
742
743	if ((osd_crop = f->dst_w + f->dst_x - f->vis_w) > 0) {
744		/* Falls off the right edge - crop */
745		f->dst_w -= osd_crop;
746		f->src_w -= (osd_scale * osd_crop) >> 16;
747	}
748
749	if (itv->yuv_info.track_osd) {
750		/* The OSD can be moved. Track to it */
751		f->dst_x += itv->yuv_info.osd_x_offset;
752		f->dst_y += itv->yuv_info.osd_y_offset;
753	}
754
755	/* Width & height for both src & dst must be even.
756	   Same for coordinates. */
757	f->dst_w &= ~1;
758	f->dst_x &= ~1;
759
760	f->src_w += f->src_x & 1;
761	f->src_x &= ~1;
762
763	f->src_w &= ~1;
764	f->dst_w &= ~1;
765
766	f->dst_h &= ~1;
767	f->dst_y &= ~1;
768
769	f->src_h += f->src_y & 1;
770	f->src_y &= ~1;
771
772	f->src_h &= ~1;
773	f->dst_h &= ~1;
774
775	/* Due to rounding, we may have reduced the output size to <1/4 of
776	   the source. Check again, but this time just resize. Don't change
777	   source coordinates */
778	if (f->dst_w < f->src_w / 4) {
779		f->src_w &= ~3;
780		f->dst_w = f->src_w / 4;
781		f->dst_w += f->dst_w & 1;
782	}
783	if (f->dst_h < f->src_h / 4) {
784		f->src_h &= ~3;
785		f->dst_h = f->src_h / 4;
786		f->dst_h += f->dst_h & 1;
787	}
788
789	/* Check again. If there's nothing to safe to display, stop now */
790	if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 ||
791	    (int)f->src_w <= 2 || (int)f->src_h <= 2) {
792		return IVTV_YUV_UPDATE_INVALID;
793	}
794
795	/* Both x offset & width are linked, so they have to be done together */
796	if ((of->dst_w != f->dst_w) || (of->src_w != f->src_w) ||
797	    (of->dst_x != f->dst_x) || (of->src_x != f->src_x) ||
798	    (of->pan_x != f->pan_x) || (of->vis_w != f->vis_w)) {
799		yuv_update |= IVTV_YUV_UPDATE_HORIZONTAL;
800	}
801
802	if ((of->src_h != f->src_h) || (of->dst_h != f->dst_h) ||
803	    (of->dst_y != f->dst_y) || (of->src_y != f->src_y) ||
804	    (of->pan_y != f->pan_y) || (of->vis_h != f->vis_h) ||
805	    (of->lace_mode != f->lace_mode) ||
806	    (of->interlaced_y != f->interlaced_y) ||
807	    (of->interlaced_uv != f->interlaced_uv)) {
808		yuv_update |= IVTV_YUV_UPDATE_VERTICAL;
809	}
810
811	return yuv_update;
812}
813
814/* Update the scaling register to the requested value */
815void ivtv_yuv_work_handler(struct ivtv *itv)
816{
817	struct yuv_playback_info *yi = &itv->yuv_info;
818	struct yuv_frame_info f;
819	int frame = yi->update_frame;
820	u32 yuv_update;
821
822	IVTV_DEBUG_YUV("Update yuv registers for frame %d\n", frame);
823	f = yi->new_frame_info[frame];
824
825	if (yi->track_osd) {
826		/* Snapshot the osd pan info */
827		f.pan_x = yi->osd_x_pan;
828		f.pan_y = yi->osd_y_pan;
829		f.vis_w = yi->osd_vis_w;
830		f.vis_h = yi->osd_vis_h;
831	} else {
832		/* Not tracking the osd, so assume full screen */
833		f.pan_x = 0;
834		f.pan_y = 0;
835		f.vis_w = 720;
836		f.vis_h = yi->decode_height;
837	}
838
839	/* Calculate the display window coordinates. Exit if nothing left */
840	if (!(yuv_update = ivtv_yuv_window_setup(itv, &f)))
841		return;
842
843	if (yuv_update & IVTV_YUV_UPDATE_INVALID) {
844		write_reg(0x01008080, 0x2898);
845	} else if (yuv_update) {
846		write_reg(0x00108080, 0x2898);
847
848		if (yuv_update & IVTV_YUV_UPDATE_HORIZONTAL)
849			ivtv_yuv_handle_horizontal(itv, &f);
850
851		if (yuv_update & IVTV_YUV_UPDATE_VERTICAL)
852			ivtv_yuv_handle_vertical(itv, &f);
853	}
854	yi->old_frame_info = f;
855}
856
857static void ivtv_yuv_init(struct ivtv *itv)
858{
859	struct yuv_playback_info *yi = &itv->yuv_info;
860
861	IVTV_DEBUG_YUV("ivtv_yuv_init\n");
862
863	/* Take a snapshot of the current register settings */
864	yi->reg_2834 = read_reg(0x02834);
865	yi->reg_2838 = read_reg(0x02838);
866	yi->reg_283c = read_reg(0x0283c);
867	yi->reg_2840 = read_reg(0x02840);
868	yi->reg_2844 = read_reg(0x02844);
869	yi->reg_2848 = read_reg(0x02848);
870	yi->reg_2854 = read_reg(0x02854);
871	yi->reg_285c = read_reg(0x0285c);
872	yi->reg_2864 = read_reg(0x02864);
873	yi->reg_2870 = read_reg(0x02870);
874	yi->reg_2874 = read_reg(0x02874);
875	yi->reg_2898 = read_reg(0x02898);
876	yi->reg_2890 = read_reg(0x02890);
877
878	yi->reg_289c = read_reg(0x0289c);
879	yi->reg_2918 = read_reg(0x02918);
880	yi->reg_291c = read_reg(0x0291c);
881	yi->reg_2920 = read_reg(0x02920);
882	yi->reg_2924 = read_reg(0x02924);
883	yi->reg_2928 = read_reg(0x02928);
884	yi->reg_292c = read_reg(0x0292c);
885	yi->reg_2930 = read_reg(0x02930);
886	yi->reg_2934 = read_reg(0x02934);
887	yi->reg_2938 = read_reg(0x02938);
888	yi->reg_293c = read_reg(0x0293c);
889	yi->reg_2940 = read_reg(0x02940);
890	yi->reg_2944 = read_reg(0x02944);
891	yi->reg_2948 = read_reg(0x02948);
892	yi->reg_294c = read_reg(0x0294c);
893	yi->reg_2950 = read_reg(0x02950);
894	yi->reg_2954 = read_reg(0x02954);
895	yi->reg_2958 = read_reg(0x02958);
896	yi->reg_295c = read_reg(0x0295c);
897	yi->reg_2960 = read_reg(0x02960);
898	yi->reg_2964 = read_reg(0x02964);
899	yi->reg_2968 = read_reg(0x02968);
900	yi->reg_296c = read_reg(0x0296c);
901	yi->reg_2970 = read_reg(0x02970);
902
903	yi->v_filter_1 = -1;
904	yi->v_filter_2 = -1;
905	yi->h_filter = -1;
906
907	/* Set some valid size info */
908	yi->osd_x_offset = read_reg(0x02a04) & 0x00000FFF;
909	yi->osd_y_offset = (read_reg(0x02a04) >> 16) & 0x00000FFF;
910
911	/* Bit 2 of reg 2878 indicates current decoder output format
912	   0 : NTSC    1 : PAL */
913	if (read_reg(0x2878) & 4)
914		yi->decode_height = 576;
915	else
916		yi->decode_height = 480;
917
918	if (!itv->osd_info) {
919		yi->osd_vis_w = 720 - yi->osd_x_offset;
920		yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
921	} else {
922		/* If no visible size set, assume full size */
923		if (!yi->osd_vis_w)
924			yi->osd_vis_w = 720 - yi->osd_x_offset;
925
926		if (!yi->osd_vis_h) {
927			yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
928		} else if (yi->osd_vis_h + yi->osd_y_offset > yi->decode_height) {
929			/* If output video standard has changed, requested height may
930			   not be legal */
931			IVTV_DEBUG_WARN("Clipping yuv output - fb size (%d) exceeds video standard limit (%d)\n",
932					yi->osd_vis_h + yi->osd_y_offset,
933					yi->decode_height);
934			yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
935		}
936	}
937
938	/* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */
939	yi->blanking_ptr = kzalloc(720 * 16, GFP_KERNEL|__GFP_NOWARN);
940	if (yi->blanking_ptr) {
941		yi->blanking_dmaptr = pci_map_single(itv->pdev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE);
942	} else {
943		yi->blanking_dmaptr = 0;
944		IVTV_DEBUG_WARN("Failed to allocate yuv blanking buffer\n");
945	}
946
947	/* Enable YUV decoder output */
948	write_reg_sync(0x01, IVTV_REG_VDM);
949
950	set_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
951	atomic_set(&yi->next_dma_frame, 0);
952}
953
954/* Get next available yuv buffer on PVR350 */
955static void ivtv_yuv_next_free(struct ivtv *itv)
956{
957	int draw, display;
958	struct yuv_playback_info *yi = &itv->yuv_info;
959
960	if (atomic_read(&yi->next_dma_frame) == -1)
961		ivtv_yuv_init(itv);
962
963	draw = atomic_read(&yi->next_fill_frame);
964	display = atomic_read(&yi->next_dma_frame);
965
966	if (display > draw)
967		display -= IVTV_YUV_BUFFERS;
968
969	if (draw - display >= yi->max_frames_buffered)
970		draw = (u8)(draw - 1) % IVTV_YUV_BUFFERS;
971	else
972		yi->new_frame_info[draw].update = 0;
973
974	yi->draw_frame = draw;
975}
976
977/* Set up frame according to ivtv_dma_frame parameters */
978static void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
979{
980	struct yuv_playback_info *yi = &itv->yuv_info;
981	u8 frame = yi->draw_frame;
982	u8 last_frame = (u8)(frame - 1) % IVTV_YUV_BUFFERS;
983	struct yuv_frame_info *nf = &yi->new_frame_info[frame];
984	struct yuv_frame_info *of = &yi->new_frame_info[last_frame];
985	int lace_threshold = yi->lace_threshold;
986
987	/* Preserve old update flag in case we're overwriting a queued frame */
988	int update = nf->update;
989
990	/* Take a snapshot of the yuv coordinate information */
991	nf->src_x = args->src.left;
992	nf->src_y = args->src.top;
993	nf->src_w = args->src.width;
994	nf->src_h = args->src.height;
995	nf->dst_x = args->dst.left;
996	nf->dst_y = args->dst.top;
997	nf->dst_w = args->dst.width;
998	nf->dst_h = args->dst.height;
999	nf->tru_x = args->dst.left;
1000	nf->tru_w = args->src_width;
1001	nf->tru_h = args->src_height;
1002
1003	/* Are we going to offset the Y plane */
1004	nf->offset_y = (nf->tru_h + nf->src_x < 512 - 16) ? 1 : 0;
1005
1006	nf->update = 0;
1007	nf->interlaced_y = 0;
1008	nf->interlaced_uv = 0;
1009	nf->delay = 0;
1010	nf->sync_field = 0;
1011	nf->lace_mode = yi->lace_mode & IVTV_YUV_MODE_MASK;
1012
1013	if (lace_threshold < 0)
1014		lace_threshold = yi->decode_height - 1;
1015
1016	/* Work out the lace settings */
1017	switch (nf->lace_mode) {
1018	case IVTV_YUV_MODE_PROGRESSIVE: /* Progressive mode */
1019		nf->interlaced = 0;
1020		if (nf->tru_h < 512 || (nf->tru_h > 576 && nf->tru_h < 1021))
1021			nf->interlaced_y = 0;
1022		else
1023			nf->interlaced_y = 1;
1024
1025		if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
1026			nf->interlaced_uv = 0;
1027		else
1028			nf->interlaced_uv = 1;
1029		break;
1030
1031	case IVTV_YUV_MODE_AUTO:
1032		if (nf->tru_h <= lace_threshold || nf->tru_h > 576 || nf->tru_w > 720) {
1033			nf->interlaced = 0;
1034			if ((nf->tru_h < 512) ||
1035			    (nf->tru_h > 576 && nf->tru_h < 1021) ||
1036			    (nf->tru_w > 720 && nf->tru_h < 1021))
1037				nf->interlaced_y = 0;
1038			else
1039				nf->interlaced_y = 1;
1040			if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
1041				nf->interlaced_uv = 0;
1042			else
1043				nf->interlaced_uv = 1;
1044		} else {
1045			nf->interlaced = 1;
1046			nf->interlaced_y = 1;
1047			nf->interlaced_uv = 1;
1048		}
1049		break;
1050
1051	case IVTV_YUV_MODE_INTERLACED: /* Interlace mode */
1052	default:
1053		nf->interlaced = 1;
1054		nf->interlaced_y = 1;
1055		nf->interlaced_uv = 1;
1056		break;
1057	}
1058
1059	if (memcmp(&yi->old_frame_info_args, nf, sizeof(*nf))) {
1060		yi->old_frame_info_args = *nf;
1061		nf->update = 1;
1062		IVTV_DEBUG_YUV("Requesting reg update for frame %d\n", frame);
1063	}
1064
1065	nf->update |= update;
1066	nf->sync_field = yi->lace_sync_field;
1067	nf->delay = nf->sync_field != of->sync_field;
1068}
1069
1070/* Frame is complete & ready for display */
1071void ivtv_yuv_frame_complete(struct ivtv *itv)
1072{
1073	atomic_set(&itv->yuv_info.next_fill_frame,
1074			(itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS);
1075}
1076
1077static int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
1078{
1079	DEFINE_WAIT(wait);
1080	int rc = 0;
1081	int got_sig = 0;
1082	/* DMA the frame */
1083	mutex_lock(&itv->udma.lock);
1084
1085	if ((rc = ivtv_yuv_prep_user_dma(itv, &itv->udma, args)) != 0) {
1086		mutex_unlock(&itv->udma.lock);
1087		return rc;
1088	}
1089
1090	ivtv_udma_prepare(itv);
1091	prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
1092	/* if no UDMA is pending and no UDMA is in progress, then the DMA
1093	   is finished */
1094	while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) ||
1095	       test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
1096		/* don't interrupt if the DMA is in progress but break off
1097		   a still pending DMA. */
1098		got_sig = signal_pending(current);
1099		if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags))
1100			break;
1101		got_sig = 0;
1102		schedule();
1103	}
1104	finish_wait(&itv->dma_waitq, &wait);
1105
1106	/* Unmap Last DMA Xfer */
1107	ivtv_udma_unmap(itv);
1108
1109	if (got_sig) {
1110		IVTV_DEBUG_INFO("User stopped YUV UDMA\n");
1111		mutex_unlock(&itv->udma.lock);
1112		return -EINTR;
1113	}
1114
1115	ivtv_yuv_frame_complete(itv);
1116
1117	mutex_unlock(&itv->udma.lock);
1118	return rc;
1119}
1120
1121/* Setup frame according to V4L2 parameters */
1122void ivtv_yuv_setup_stream_frame(struct ivtv *itv)
1123{
1124	struct yuv_playback_info *yi = &itv->yuv_info;
1125	struct ivtv_dma_frame dma_args;
1126
1127	ivtv_yuv_next_free(itv);
1128
1129	/* Copy V4L2 parameters to an ivtv_dma_frame struct... */
1130	dma_args.y_source = NULL;
1131	dma_args.uv_source = NULL;
1132	dma_args.src.left = 0;
1133	dma_args.src.top = 0;
1134	dma_args.src.width = yi->v4l2_src_w;
1135	dma_args.src.height = yi->v4l2_src_h;
1136	dma_args.dst = yi->main_rect;
1137	dma_args.src_width = yi->v4l2_src_w;
1138	dma_args.src_height = yi->v4l2_src_h;
1139
1140	/* ... and use the same setup routine as ivtv_yuv_prep_frame */
1141	ivtv_yuv_setup_frame(itv, &dma_args);
1142
1143	if (!itv->dma_data_req_offset)
1144		itv->dma_data_req_offset = yuv_offset[yi->draw_frame];
1145}
1146
1147/* Attempt to dma a frame from a user buffer */
1148int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src)
1149{
1150	struct yuv_playback_info *yi = &itv->yuv_info;
1151	struct ivtv_dma_frame dma_args;
1152	int res;
1153
1154	ivtv_yuv_setup_stream_frame(itv);
1155
1156	/* We only need to supply source addresses for this */
1157	dma_args.y_source = src;
1158	dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31);
1159	/* Wait for frame DMA. Note that serialize_lock is locked,
1160	   so to allow other processes to access the driver while
1161	   we are waiting unlock first and later lock again. */
1162	mutex_unlock(&itv->serialize_lock);
1163	res = ivtv_yuv_udma_frame(itv, &dma_args);
1164	mutex_lock(&itv->serialize_lock);
1165	return res;
1166}
1167
1168/* IVTV_IOC_DMA_FRAME ioctl handler */
1169int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
1170{
1171	int res;
1172
1173/*	IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
1174	ivtv_yuv_next_free(itv);
1175	ivtv_yuv_setup_frame(itv, args);
1176	/* Wait for frame DMA. Note that serialize_lock is locked,
1177	   so to allow other processes to access the driver while
1178	   we are waiting unlock first and later lock again. */
1179	mutex_unlock(&itv->serialize_lock);
1180	res = ivtv_yuv_udma_frame(itv, args);
1181	mutex_lock(&itv->serialize_lock);
1182	return res;
1183}
1184
1185void ivtv_yuv_close(struct ivtv *itv)
1186{
1187	struct yuv_playback_info *yi = &itv->yuv_info;
1188	int h_filter, v_filter_1, v_filter_2;
1189
1190	IVTV_DEBUG_YUV("ivtv_yuv_close\n");
1191	mutex_unlock(&itv->serialize_lock);
1192	ivtv_waitq(&itv->vsync_waitq);
1193	mutex_lock(&itv->serialize_lock);
1194
1195	yi->running = 0;
1196	atomic_set(&yi->next_dma_frame, -1);
1197	atomic_set(&yi->next_fill_frame, 0);
1198
1199	/* Reset registers we have changed so mpeg playback works */
1200
1201	/* If we fully restore this register, the display may remain active.
1202	   Restore, but set one bit to blank the video. Firmware will always
1203	   clear this bit when needed, so not a problem. */
1204	write_reg(yi->reg_2898 | 0x01000000, 0x2898);
1205
1206	write_reg(yi->reg_2834, 0x02834);
1207	write_reg(yi->reg_2838, 0x02838);
1208	write_reg(yi->reg_283c, 0x0283c);
1209	write_reg(yi->reg_2840, 0x02840);
1210	write_reg(yi->reg_2844, 0x02844);
1211	write_reg(yi->reg_2848, 0x02848);
1212	write_reg(yi->reg_2854, 0x02854);
1213	write_reg(yi->reg_285c, 0x0285c);
1214	write_reg(yi->reg_2864, 0x02864);
1215	write_reg(yi->reg_2870, 0x02870);
1216	write_reg(yi->reg_2874, 0x02874);
1217	write_reg(yi->reg_2890, 0x02890);
1218	write_reg(yi->reg_289c, 0x0289c);
1219
1220	write_reg(yi->reg_2918, 0x02918);
1221	write_reg(yi->reg_291c, 0x0291c);
1222	write_reg(yi->reg_2920, 0x02920);
1223	write_reg(yi->reg_2924, 0x02924);
1224	write_reg(yi->reg_2928, 0x02928);
1225	write_reg(yi->reg_292c, 0x0292c);
1226	write_reg(yi->reg_2930, 0x02930);
1227	write_reg(yi->reg_2934, 0x02934);
1228	write_reg(yi->reg_2938, 0x02938);
1229	write_reg(yi->reg_293c, 0x0293c);
1230	write_reg(yi->reg_2940, 0x02940);
1231	write_reg(yi->reg_2944, 0x02944);
1232	write_reg(yi->reg_2948, 0x02948);
1233	write_reg(yi->reg_294c, 0x0294c);
1234	write_reg(yi->reg_2950, 0x02950);
1235	write_reg(yi->reg_2954, 0x02954);
1236	write_reg(yi->reg_2958, 0x02958);
1237	write_reg(yi->reg_295c, 0x0295c);
1238	write_reg(yi->reg_2960, 0x02960);
1239	write_reg(yi->reg_2964, 0x02964);
1240	write_reg(yi->reg_2968, 0x02968);
1241	write_reg(yi->reg_296c, 0x0296c);
1242	write_reg(yi->reg_2970, 0x02970);
1243
1244	/* Prepare to restore filters */
1245
1246	/* First the horizontal filter */
1247	if ((yi->reg_2834 & 0x0000FFFF) == (yi->reg_2834 >> 16)) {
1248		/* An exact size match uses filter 0 */
1249		h_filter = 0;
1250	} else {
1251		/* Figure out which filter to use */
1252		h_filter = ((yi->reg_2834 << 16) / (yi->reg_2834 >> 16)) >> 15;
1253		h_filter = (h_filter >> 1) + (h_filter & 1);
1254		/* Only an exact size match can use filter 0. */
1255		h_filter += !h_filter;
1256	}
1257
1258	/* Now the vertical filter */
1259	if ((yi->reg_2918 & 0x0000FFFF) == (yi->reg_2918 >> 16)) {
1260		/* An exact size match uses filter 0/1 */
1261		v_filter_1 = 0;
1262		v_filter_2 = 1;
1263	} else {
1264		/* Figure out which filter to use */
1265		v_filter_1 = ((yi->reg_2918 << 16) / (yi->reg_2918 >> 16)) >> 15;
1266		v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1);
1267		/* Only an exact size match can use filter 0 */
1268		v_filter_1 += !v_filter_1;
1269		v_filter_2 = v_filter_1;
1270	}
1271
1272	/* Now restore the filters */
1273	ivtv_yuv_filter(itv, h_filter, v_filter_1, v_filter_2);
1274
1275	/* and clear a few registers */
1276	write_reg(0, 0x02814);
1277	write_reg(0, 0x0282c);
1278	write_reg(0, 0x02904);
1279	write_reg(0, 0x02910);
1280
1281	/* Release the blanking buffer */
1282	if (yi->blanking_ptr) {
1283		kfree(yi->blanking_ptr);
1284		yi->blanking_ptr = NULL;
1285		pci_unmap_single(itv->pdev, yi->blanking_dmaptr, 720*16, PCI_DMA_TODEVICE);
1286	}
1287
1288	/* Invalidate the old dimension information */
1289	yi->old_frame_info.src_w = 0;
1290	yi->old_frame_info.src_h = 0;
1291	yi->old_frame_info_args.src_w = 0;
1292	yi->old_frame_info_args.src_h = 0;
1293
1294	/* All done. */
1295	clear_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
1296}
1297