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