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