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