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