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