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