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