• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ivtv_yuv_prep_user_dma(struct ivtv * itv,struct ivtv_user_dma * dma,struct ivtv_dma_frame * args)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 = pci_map_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE);
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. */
ivtv_yuv_filter_check(struct ivtv * itv)137 int 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 
ivtv_yuv_filter(struct ivtv * itv,int h_filter,int v_filter_1,int v_filter_2)151 static 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 
ivtv_yuv_handle_horizontal(struct ivtv * itv,struct yuv_frame_info * f)211 static 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 
ivtv_yuv_handle_vertical(struct ivtv * itv,struct yuv_frame_info * f)373 static 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 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 */
ivtv_yuv_window_setup(struct ivtv * itv,struct yuv_frame_info * f)652 static 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 */
ivtv_yuv_work_handler(struct ivtv * itv)797 void 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 
ivtv_yuv_init(struct ivtv * itv)839 static 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 = pci_map_single(itv->pdev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE);
924 	} else {
925 		yi->blanking_dmaptr = 0;
926 		IVTV_DEBUG_WARN("Failed to allocate yuv blanking buffer\n");
927 	}
928 
929 	/* Enable YUV decoder output */
930 	write_reg_sync(0x01, IVTV_REG_VDM);
931 
932 	set_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
933 	atomic_set(&yi->next_dma_frame, 0);
934 }
935 
936 /* Get next available yuv buffer on PVR350 */
ivtv_yuv_next_free(struct ivtv * itv)937 static void ivtv_yuv_next_free(struct ivtv *itv)
938 {
939 	int draw, display;
940 	struct yuv_playback_info *yi = &itv->yuv_info;
941 
942 	if (atomic_read(&yi->next_dma_frame) == -1)
943 		ivtv_yuv_init(itv);
944 
945 	draw = atomic_read(&yi->next_fill_frame);
946 	display = atomic_read(&yi->next_dma_frame);
947 
948 	if (display > draw)
949 		display -= IVTV_YUV_BUFFERS;
950 
951 	if (draw - display >= yi->max_frames_buffered)
952 		draw = (u8)(draw - 1) % IVTV_YUV_BUFFERS;
953 	else
954 		yi->new_frame_info[draw].update = 0;
955 
956 	yi->draw_frame = draw;
957 }
958 
959 /* Set up frame according to ivtv_dma_frame parameters */
ivtv_yuv_setup_frame(struct ivtv * itv,struct ivtv_dma_frame * args)960 static void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
961 {
962 	struct yuv_playback_info *yi = &itv->yuv_info;
963 	u8 frame = yi->draw_frame;
964 	u8 last_frame = (u8)(frame - 1) % IVTV_YUV_BUFFERS;
965 	struct yuv_frame_info *nf = &yi->new_frame_info[frame];
966 	struct yuv_frame_info *of = &yi->new_frame_info[last_frame];
967 	int lace_threshold = yi->lace_threshold;
968 
969 	/* Preserve old update flag in case we're overwriting a queued frame */
970 	int update = nf->update;
971 
972 	/* Take a snapshot of the yuv coordinate information */
973 	nf->src_x = args->src.left;
974 	nf->src_y = args->src.top;
975 	nf->src_w = args->src.width;
976 	nf->src_h = args->src.height;
977 	nf->dst_x = args->dst.left;
978 	nf->dst_y = args->dst.top;
979 	nf->dst_w = args->dst.width;
980 	nf->dst_h = args->dst.height;
981 	nf->tru_x = args->dst.left;
982 	nf->tru_w = args->src_width;
983 	nf->tru_h = args->src_height;
984 
985 	/* Are we going to offset the Y plane */
986 	nf->offset_y = (nf->tru_h + nf->src_x < 512 - 16) ? 1 : 0;
987 
988 	nf->update = 0;
989 	nf->interlaced_y = 0;
990 	nf->interlaced_uv = 0;
991 	nf->delay = 0;
992 	nf->sync_field = 0;
993 	nf->lace_mode = yi->lace_mode & IVTV_YUV_MODE_MASK;
994 
995 	if (lace_threshold < 0)
996 		lace_threshold = yi->decode_height - 1;
997 
998 	/* Work out the lace settings */
999 	switch (nf->lace_mode) {
1000 	case IVTV_YUV_MODE_PROGRESSIVE: /* Progressive mode */
1001 		nf->interlaced = 0;
1002 		if (nf->tru_h < 512 || (nf->tru_h > 576 && nf->tru_h < 1021))
1003 			nf->interlaced_y = 0;
1004 		else
1005 			nf->interlaced_y = 1;
1006 
1007 		if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
1008 			nf->interlaced_uv = 0;
1009 		else
1010 			nf->interlaced_uv = 1;
1011 		break;
1012 
1013 	case IVTV_YUV_MODE_AUTO:
1014 		if (nf->tru_h <= lace_threshold || nf->tru_h > 576 || nf->tru_w > 720) {
1015 			nf->interlaced = 0;
1016 			if ((nf->tru_h < 512) ||
1017 			    (nf->tru_h > 576 && nf->tru_h < 1021) ||
1018 			    (nf->tru_w > 720 && nf->tru_h < 1021))
1019 				nf->interlaced_y = 0;
1020 			else
1021 				nf->interlaced_y = 1;
1022 			if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
1023 				nf->interlaced_uv = 0;
1024 			else
1025 				nf->interlaced_uv = 1;
1026 		} else {
1027 			nf->interlaced = 1;
1028 			nf->interlaced_y = 1;
1029 			nf->interlaced_uv = 1;
1030 		}
1031 		break;
1032 
1033 	case IVTV_YUV_MODE_INTERLACED: /* Interlace mode */
1034 	default:
1035 		nf->interlaced = 1;
1036 		nf->interlaced_y = 1;
1037 		nf->interlaced_uv = 1;
1038 		break;
1039 	}
1040 
1041 	if (memcmp(&yi->old_frame_info_args, nf, sizeof(*nf))) {
1042 		yi->old_frame_info_args = *nf;
1043 		nf->update = 1;
1044 		IVTV_DEBUG_YUV("Requesting reg update for frame %d\n", frame);
1045 	}
1046 
1047 	nf->update |= update;
1048 	nf->sync_field = yi->lace_sync_field;
1049 	nf->delay = nf->sync_field != of->sync_field;
1050 }
1051 
1052 /* Frame is complete & ready for display */
ivtv_yuv_frame_complete(struct ivtv * itv)1053 void ivtv_yuv_frame_complete(struct ivtv *itv)
1054 {
1055 	atomic_set(&itv->yuv_info.next_fill_frame,
1056 			(itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS);
1057 }
1058 
ivtv_yuv_udma_frame(struct ivtv * itv,struct ivtv_dma_frame * args)1059 static int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
1060 {
1061 	DEFINE_WAIT(wait);
1062 	int rc = 0;
1063 	int got_sig = 0;
1064 	/* DMA the frame */
1065 	mutex_lock(&itv->udma.lock);
1066 
1067 	if ((rc = ivtv_yuv_prep_user_dma(itv, &itv->udma, args)) != 0) {
1068 		mutex_unlock(&itv->udma.lock);
1069 		return rc;
1070 	}
1071 
1072 	ivtv_udma_prepare(itv);
1073 	prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
1074 	/* if no UDMA is pending and no UDMA is in progress, then the DMA
1075 	   is finished */
1076 	while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) ||
1077 	       test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
1078 		/* don't interrupt if the DMA is in progress but break off
1079 		   a still pending DMA. */
1080 		got_sig = signal_pending(current);
1081 		if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags))
1082 			break;
1083 		got_sig = 0;
1084 		schedule();
1085 	}
1086 	finish_wait(&itv->dma_waitq, &wait);
1087 
1088 	/* Unmap Last DMA Xfer */
1089 	ivtv_udma_unmap(itv);
1090 
1091 	if (got_sig) {
1092 		IVTV_DEBUG_INFO("User stopped YUV UDMA\n");
1093 		mutex_unlock(&itv->udma.lock);
1094 		return -EINTR;
1095 	}
1096 
1097 	ivtv_yuv_frame_complete(itv);
1098 
1099 	mutex_unlock(&itv->udma.lock);
1100 	return rc;
1101 }
1102 
1103 /* Setup frame according to V4L2 parameters */
ivtv_yuv_setup_stream_frame(struct ivtv * itv)1104 void ivtv_yuv_setup_stream_frame(struct ivtv *itv)
1105 {
1106 	struct yuv_playback_info *yi = &itv->yuv_info;
1107 	struct ivtv_dma_frame dma_args;
1108 
1109 	ivtv_yuv_next_free(itv);
1110 
1111 	/* Copy V4L2 parameters to an ivtv_dma_frame struct... */
1112 	dma_args.y_source = NULL;
1113 	dma_args.uv_source = NULL;
1114 	dma_args.src.left = 0;
1115 	dma_args.src.top = 0;
1116 	dma_args.src.width = yi->v4l2_src_w;
1117 	dma_args.src.height = yi->v4l2_src_h;
1118 	dma_args.dst = yi->main_rect;
1119 	dma_args.src_width = yi->v4l2_src_w;
1120 	dma_args.src_height = yi->v4l2_src_h;
1121 
1122 	/* ... and use the same setup routine as ivtv_yuv_prep_frame */
1123 	ivtv_yuv_setup_frame(itv, &dma_args);
1124 
1125 	if (!itv->dma_data_req_offset)
1126 		itv->dma_data_req_offset = yuv_offset[yi->draw_frame];
1127 }
1128 
1129 /* Attempt to dma a frame from a user buffer */
ivtv_yuv_udma_stream_frame(struct ivtv * itv,void __user * src)1130 int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src)
1131 {
1132 	struct yuv_playback_info *yi = &itv->yuv_info;
1133 	struct ivtv_dma_frame dma_args;
1134 	int res;
1135 
1136 	ivtv_yuv_setup_stream_frame(itv);
1137 
1138 	/* We only need to supply source addresses for this */
1139 	dma_args.y_source = src;
1140 	dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31);
1141 	/* Wait for frame DMA. Note that serialize_lock is locked,
1142 	   so to allow other processes to access the driver while
1143 	   we are waiting unlock first and later lock again. */
1144 	mutex_unlock(&itv->serialize_lock);
1145 	res = ivtv_yuv_udma_frame(itv, &dma_args);
1146 	mutex_lock(&itv->serialize_lock);
1147 	return res;
1148 }
1149 
1150 /* IVTV_IOC_DMA_FRAME ioctl handler */
ivtv_yuv_prep_frame(struct ivtv * itv,struct ivtv_dma_frame * args)1151 int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
1152 {
1153 	int res;
1154 
1155 /*	IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
1156 	ivtv_yuv_next_free(itv);
1157 	ivtv_yuv_setup_frame(itv, args);
1158 	/* Wait for frame DMA. Note that serialize_lock is locked,
1159 	   so to allow other processes to access the driver while
1160 	   we are waiting unlock first and later lock again. */
1161 	mutex_unlock(&itv->serialize_lock);
1162 	res = ivtv_yuv_udma_frame(itv, args);
1163 	mutex_lock(&itv->serialize_lock);
1164 	return res;
1165 }
1166 
ivtv_yuv_close(struct ivtv * itv)1167 void ivtv_yuv_close(struct ivtv *itv)
1168 {
1169 	struct yuv_playback_info *yi = &itv->yuv_info;
1170 	int h_filter, v_filter_1, v_filter_2;
1171 
1172 	IVTV_DEBUG_YUV("ivtv_yuv_close\n");
1173 	mutex_unlock(&itv->serialize_lock);
1174 	ivtv_waitq(&itv->vsync_waitq);
1175 	mutex_lock(&itv->serialize_lock);
1176 
1177 	yi->running = 0;
1178 	atomic_set(&yi->next_dma_frame, -1);
1179 	atomic_set(&yi->next_fill_frame, 0);
1180 
1181 	/* Reset registers we have changed so mpeg playback works */
1182 
1183 	/* If we fully restore this register, the display may remain active.
1184 	   Restore, but set one bit to blank the video. Firmware will always
1185 	   clear this bit when needed, so not a problem. */
1186 	write_reg(yi->reg_2898 | 0x01000000, 0x2898);
1187 
1188 	write_reg(yi->reg_2834, 0x02834);
1189 	write_reg(yi->reg_2838, 0x02838);
1190 	write_reg(yi->reg_283c, 0x0283c);
1191 	write_reg(yi->reg_2840, 0x02840);
1192 	write_reg(yi->reg_2844, 0x02844);
1193 	write_reg(yi->reg_2848, 0x02848);
1194 	write_reg(yi->reg_2854, 0x02854);
1195 	write_reg(yi->reg_285c, 0x0285c);
1196 	write_reg(yi->reg_2864, 0x02864);
1197 	write_reg(yi->reg_2870, 0x02870);
1198 	write_reg(yi->reg_2874, 0x02874);
1199 	write_reg(yi->reg_2890, 0x02890);
1200 	write_reg(yi->reg_289c, 0x0289c);
1201 
1202 	write_reg(yi->reg_2918, 0x02918);
1203 	write_reg(yi->reg_291c, 0x0291c);
1204 	write_reg(yi->reg_2920, 0x02920);
1205 	write_reg(yi->reg_2924, 0x02924);
1206 	write_reg(yi->reg_2928, 0x02928);
1207 	write_reg(yi->reg_292c, 0x0292c);
1208 	write_reg(yi->reg_2930, 0x02930);
1209 	write_reg(yi->reg_2934, 0x02934);
1210 	write_reg(yi->reg_2938, 0x02938);
1211 	write_reg(yi->reg_293c, 0x0293c);
1212 	write_reg(yi->reg_2940, 0x02940);
1213 	write_reg(yi->reg_2944, 0x02944);
1214 	write_reg(yi->reg_2948, 0x02948);
1215 	write_reg(yi->reg_294c, 0x0294c);
1216 	write_reg(yi->reg_2950, 0x02950);
1217 	write_reg(yi->reg_2954, 0x02954);
1218 	write_reg(yi->reg_2958, 0x02958);
1219 	write_reg(yi->reg_295c, 0x0295c);
1220 	write_reg(yi->reg_2960, 0x02960);
1221 	write_reg(yi->reg_2964, 0x02964);
1222 	write_reg(yi->reg_2968, 0x02968);
1223 	write_reg(yi->reg_296c, 0x0296c);
1224 	write_reg(yi->reg_2970, 0x02970);
1225 
1226 	/* Prepare to restore filters */
1227 
1228 	/* First the horizontal filter */
1229 	if ((yi->reg_2834 & 0x0000FFFF) == (yi->reg_2834 >> 16)) {
1230 		/* An exact size match uses filter 0 */
1231 		h_filter = 0;
1232 	} else {
1233 		/* Figure out which filter to use */
1234 		h_filter = ((yi->reg_2834 << 16) / (yi->reg_2834 >> 16)) >> 15;
1235 		h_filter = (h_filter >> 1) + (h_filter & 1);
1236 		/* Only an exact size match can use filter 0. */
1237 		h_filter += !h_filter;
1238 	}
1239 
1240 	/* Now the vertical filter */
1241 	if ((yi->reg_2918 & 0x0000FFFF) == (yi->reg_2918 >> 16)) {
1242 		/* An exact size match uses filter 0/1 */
1243 		v_filter_1 = 0;
1244 		v_filter_2 = 1;
1245 	} else {
1246 		/* Figure out which filter to use */
1247 		v_filter_1 = ((yi->reg_2918 << 16) / (yi->reg_2918 >> 16)) >> 15;
1248 		v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1);
1249 		/* Only an exact size match can use filter 0 */
1250 		v_filter_1 += !v_filter_1;
1251 		v_filter_2 = v_filter_1;
1252 	}
1253 
1254 	/* Now restore the filters */
1255 	ivtv_yuv_filter(itv, h_filter, v_filter_1, v_filter_2);
1256 
1257 	/* and clear a few registers */
1258 	write_reg(0, 0x02814);
1259 	write_reg(0, 0x0282c);
1260 	write_reg(0, 0x02904);
1261 	write_reg(0, 0x02910);
1262 
1263 	/* Release the blanking buffer */
1264 	if (yi->blanking_ptr) {
1265 		kfree(yi->blanking_ptr);
1266 		yi->blanking_ptr = NULL;
1267 		pci_unmap_single(itv->pdev, yi->blanking_dmaptr, 720*16, PCI_DMA_TODEVICE);
1268 	}
1269 
1270 	/* Invalidate the old dimension information */
1271 	yi->old_frame_info.src_w = 0;
1272 	yi->old_frame_info.src_h = 0;
1273 	yi->old_frame_info_args.src_w = 0;
1274 	yi->old_frame_info_args.src_h = 0;
1275 
1276 	/* All done. */
1277 	clear_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
1278 }
1279