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