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