xref: /openbmc/linux/drivers/media/pci/ivtv/ivtv-yuv.c (revision 70b96f24)
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], 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. */
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 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 = 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 */
ivtv_yuv_next_free(struct ivtv * itv)939 static 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 */
ivtv_yuv_setup_frame(struct ivtv * itv,struct ivtv_dma_frame * args)962 static 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 */
ivtv_yuv_frame_complete(struct ivtv * itv)1055 void 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 
ivtv_yuv_udma_frame(struct ivtv * itv,struct ivtv_dma_frame * args)1061 static 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 */
ivtv_yuv_setup_stream_frame(struct ivtv * itv)1106 void 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 */
ivtv_yuv_udma_stream_frame(struct ivtv * itv,void __user * src)1132 int 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 */
ivtv_yuv_prep_frame(struct ivtv * itv,struct ivtv_dma_frame * args)1153 int 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 
ivtv_yuv_close(struct ivtv * itv)1169 void 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