V4L/DVB (5405): Add missing includes.
[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         itv->yuv_info.frame_interlaced_last = itv->yuv_info.frame_interlaced;
616         itv->yuv_info.lace_threshold_last = itv->yuv_info.lace_threshold;
617 }
618
619 /* Modify the supplied coordinate information to fit the visible osd area */
620 static u32 ivtv_yuv_window_setup (struct ivtv *itv, struct yuv_frame_info *window)
621 {
622         int osd_crop;
623         u32 osd_scale;
624         u32 yuv_update = 0;
625
626         /* Work out the lace settings */
627         switch (itv->yuv_info.lace_mode) {
628                 case IVTV_YUV_MODE_PROGRESSIVE: /* Progressive mode */
629                         itv->yuv_info.frame_interlaced = 0;
630                         if (window->tru_h < 512 || (window->tru_h > 576 && window->tru_h < 1021))
631                                 window->interlaced_y = 0;
632                         else
633                                 window->interlaced_y = 1;
634
635                         if (window->tru_h < 1021 && (window->dst_h >= window->src_h /2))
636                                 window->interlaced_uv = 0;
637                         else
638                                 window->interlaced_uv = 1;
639                         break;
640
641                 case IVTV_YUV_MODE_AUTO:
642                         if (window->tru_h <= itv->yuv_info.lace_threshold || window->tru_h > 576 || window->tru_w > 720){
643                                 itv->yuv_info.frame_interlaced = 0;
644                                 if ((window->tru_h < 512) ||
645                                   (window->tru_h > 576 && window->tru_h < 1021) ||
646                                   (window->tru_w > 720 && window->tru_h < 1021))
647                                         window->interlaced_y = 0;
648                                 else
649                                         window->interlaced_y = 1;
650
651                                 if (window->tru_h < 1021 && (window->dst_h >= window->src_h /2))
652                                         window->interlaced_uv = 0;
653                                 else
654                                         window->interlaced_uv = 1;
655                         }
656                         else {
657                                 itv->yuv_info.frame_interlaced = 1;
658                                 window->interlaced_y = 1;
659                                 window->interlaced_uv = 1;
660                         }
661                         break;
662
663                         case IVTV_YUV_MODE_INTERLACED: /* Interlace mode */
664                 default:
665                         itv->yuv_info.frame_interlaced = 1;
666                         window->interlaced_y = 1;
667                         window->interlaced_uv = 1;
668                         break;
669         }
670
671         /* Sorry, but no negative coords for src */
672         if (window->src_x < 0) window->src_x = 0;
673         if (window->src_y < 0) window->src_y = 0;
674
675         /* Can only reduce width down to 1/4 original size */
676         if ((osd_crop = window->src_w - ( 4 * window->dst_w )) > 0) {
677                 window->src_x += osd_crop / 2;
678                 window->src_w = (window->src_w - osd_crop) & ~3;
679                 window->dst_w = window->src_w / 4;
680                 window->dst_w += window->dst_w & 1;
681         }
682
683         /* Can only reduce height down to 1/4 original size */
684         if (window->src_h / window->dst_h >= 2) {
685                 /* Overflow may be because we're running progressive, so force mode switch */
686                 window->interlaced_y = 1;
687                 /* Make sure we're still within limits for interlace */
688                 if ((osd_crop = window->src_h - ( 4 * window->dst_h )) > 0) {
689                         /* If we reach here we'll have to force the height. */
690                         window->src_y += osd_crop / 2;
691                         window->src_h = (window->src_h - osd_crop) & ~3;
692                         window->dst_h = window->src_h / 4;
693                         window->dst_h += window->dst_h & 1;
694                 }
695         }
696
697         /* If there's nothing to safe to display, we may as well stop now */
698         if ((int)window->dst_w <= 2 || (int)window->dst_h <= 2 || (int)window->src_w <= 2 || (int)window->src_h <= 2) {
699                 return 0;
700         }
701
702         /* Ensure video remains inside OSD area */
703         osd_scale = (window->src_h << 16) / window->dst_h;
704
705         if ((osd_crop = window->pan_y - window->dst_y) > 0) {
706                 /* Falls off the upper edge - crop */
707                 window->src_y += (osd_scale * osd_crop) >> 16;
708                 window->src_h -= (osd_scale * osd_crop) >> 16;
709                 window->dst_h -= osd_crop;
710                 window->dst_y = 0;
711         }
712         else {
713                 window->dst_y -= window->pan_y;
714         }
715
716         if ((osd_crop = window->dst_h + window->dst_y - window->vis_h) > 0) {
717                 /* Falls off the lower edge - crop */
718                 window->dst_h -= osd_crop;
719                 window->src_h -= (osd_scale * osd_crop) >> 16;
720         }
721
722         osd_scale = (window->src_w << 16) / window->dst_w;
723
724         if ((osd_crop = window->pan_x - window->dst_x) > 0) {
725                 /* Fall off the left edge - crop */
726                 window->src_x += (osd_scale * osd_crop) >> 16;
727                 window->src_w -= (osd_scale * osd_crop) >> 16;
728                 window->dst_w -= osd_crop;
729                 window->dst_x = 0;
730         }
731         else {
732                 window->dst_x -= window->pan_x;
733         }
734
735         if ((osd_crop = window->dst_w + window->dst_x - window->vis_w) > 0) {
736                 /* Falls off the right edge - crop */
737                 window->dst_w -= osd_crop;
738                 window->src_w -= (osd_scale * osd_crop) >> 16;
739         }
740
741         /* The OSD can be moved. Track to it */
742         window->dst_x += itv->yuv_info.osd_x_offset;
743         window->dst_y += itv->yuv_info.osd_y_offset;
744
745         /* Width & height for both src & dst must be even.
746            Same for coordinates. */
747         window->dst_w &= ~1;
748         window->dst_x &= ~1;
749
750         window->src_w += window->src_x & 1;
751         window->src_x &= ~1;
752
753         window->src_w &= ~1;
754         window->dst_w &= ~1;
755
756         window->dst_h &= ~1;
757         window->dst_y &= ~1;
758
759         window->src_h += window->src_y & 1;
760         window->src_y &= ~1;
761
762         window->src_h &= ~1;
763         window->dst_h &= ~1;
764
765         /* Due to rounding, we may have reduced the output size to <1/4 of the source
766            Check again, but this time just resize. Don't change source coordinates */
767         if (window->dst_w < window->src_w / 4) {
768                 window->src_w &= ~3;
769                 window->dst_w = window->src_w / 4;
770                 window->dst_w += window->dst_w & 1;
771         }
772         if (window->dst_h < window->src_h / 4) {
773                 window->src_h &= ~3;
774                 window->dst_h = window->src_h / 4;
775                 window->dst_h += window->dst_h & 1;
776         }
777
778         /* Check again. If there's nothing to safe to display, stop now */
779         if ((int)window->dst_w <= 2 || (int)window->dst_h <= 2 || (int)window->src_w <= 2 || (int)window->src_h <= 2) {
780                 return 0;
781         }
782
783         /* Both x offset & width are linked, so they have to be done together */
784         if ((itv->yuv_info.old_frame_info.dst_w != window->dst_w) ||
785             (itv->yuv_info.old_frame_info.src_w != window->src_w) ||
786             (itv->yuv_info.old_frame_info.dst_x != window->dst_x) ||
787             (itv->yuv_info.old_frame_info.src_x != window->src_x) ||
788             (itv->yuv_info.old_frame_info.pan_x != window->pan_x) ||
789             (itv->yuv_info.old_frame_info.vis_w != window->vis_w)) {
790                 yuv_update |= IVTV_YUV_UPDATE_HORIZONTAL;
791         }
792
793         if ((itv->yuv_info.old_frame_info.src_h != window->src_h) ||
794             (itv->yuv_info.old_frame_info.dst_h != window->dst_h) ||
795             (itv->yuv_info.old_frame_info.dst_y != window->dst_y) ||
796             (itv->yuv_info.old_frame_info.src_y != window->src_y) ||
797             (itv->yuv_info.old_frame_info.pan_y != window->pan_y) ||
798             (itv->yuv_info.old_frame_info.vis_h != window->vis_h) ||
799             (itv->yuv_info.old_frame_info.interlaced_y != window->interlaced_y) ||
800             (itv->yuv_info.old_frame_info.interlaced_uv != window->interlaced_uv)) {
801                 yuv_update |= IVTV_YUV_UPDATE_VERTICAL;
802         }
803
804         return yuv_update;
805 }
806
807 /* Update the scaling register to the requested value */
808 void ivtv_yuv_work_handler (struct ivtv *itv)
809 {
810         struct yuv_frame_info window;
811         u32 yuv_update;
812
813         int frame = itv->yuv_info.update_frame;
814
815 /*      IVTV_DEBUG_YUV("Update yuv registers for frame %d\n",frame); */
816         memcpy(&window, &itv->yuv_info.new_frame_info[frame], sizeof (window));
817
818         /* Update the osd pan info */
819         window.pan_x = itv->yuv_info.osd_x_pan;
820         window.pan_y = itv->yuv_info.osd_y_pan;
821         window.vis_w = itv->yuv_info.osd_vis_w;
822         window.vis_h = itv->yuv_info.osd_vis_h;
823
824         /* Calculate the display window coordinates. Exit if nothing left */
825         if (!(yuv_update = ivtv_yuv_window_setup (itv, &window)))
826                 return;
827
828         /* Update horizontal settings */
829         if (yuv_update & IVTV_YUV_UPDATE_HORIZONTAL)
830                 ivtv_yuv_handle_horizontal(itv, &window);
831
832         if (yuv_update & IVTV_YUV_UPDATE_VERTICAL)
833                 ivtv_yuv_handle_vertical(itv, &window);
834
835         memcpy(&itv->yuv_info.old_frame_info, &window, sizeof (itv->yuv_info.old_frame_info));
836 }
837
838 static void ivtv_yuv_init (struct ivtv *itv)
839 {
840         IVTV_DEBUG_YUV("ivtv_yuv_init\n");
841
842         /* Take a snapshot of the current register settings */
843         itv->yuv_info.reg_2834 = read_reg(0x02834);
844         itv->yuv_info.reg_2838 = read_reg(0x02838);
845         itv->yuv_info.reg_283c = read_reg(0x0283c);
846         itv->yuv_info.reg_2840 = read_reg(0x02840);
847         itv->yuv_info.reg_2844 = read_reg(0x02844);
848         itv->yuv_info.reg_2848 = read_reg(0x02848);
849         itv->yuv_info.reg_2854 = read_reg(0x02854);
850         itv->yuv_info.reg_285c = read_reg(0x0285c);
851         itv->yuv_info.reg_2864 = read_reg(0x02864);
852         itv->yuv_info.reg_2870 = read_reg(0x02870);
853         itv->yuv_info.reg_2874 = read_reg(0x02874);
854         itv->yuv_info.reg_2898 = read_reg(0x02898);
855         itv->yuv_info.reg_2890 = read_reg(0x02890);
856
857         itv->yuv_info.reg_289c = read_reg(0x0289c);
858         itv->yuv_info.reg_2918 = read_reg(0x02918);
859         itv->yuv_info.reg_291c = read_reg(0x0291c);
860         itv->yuv_info.reg_2920 = read_reg(0x02920);
861         itv->yuv_info.reg_2924 = read_reg(0x02924);
862         itv->yuv_info.reg_2928 = read_reg(0x02928);
863         itv->yuv_info.reg_292c = read_reg(0x0292c);
864         itv->yuv_info.reg_2930 = read_reg(0x02930);
865         itv->yuv_info.reg_2934 = read_reg(0x02934);
866         itv->yuv_info.reg_2938 = read_reg(0x02938);
867         itv->yuv_info.reg_293c = read_reg(0x0293c);
868         itv->yuv_info.reg_2940 = read_reg(0x02940);
869         itv->yuv_info.reg_2944 = read_reg(0x02944);
870         itv->yuv_info.reg_2948 = read_reg(0x02948);
871         itv->yuv_info.reg_294c = read_reg(0x0294c);
872         itv->yuv_info.reg_2950 = read_reg(0x02950);
873         itv->yuv_info.reg_2954 = read_reg(0x02954);
874         itv->yuv_info.reg_2958 = read_reg(0x02958);
875         itv->yuv_info.reg_295c = read_reg(0x0295c);
876         itv->yuv_info.reg_2960 = read_reg(0x02960);
877         itv->yuv_info.reg_2964 = read_reg(0x02964);
878         itv->yuv_info.reg_2968 = read_reg(0x02968);
879         itv->yuv_info.reg_296c = read_reg(0x0296c);
880         itv->yuv_info.reg_2970 = read_reg(0x02970);
881
882         itv->yuv_info.v_filter_1 = -1;
883         itv->yuv_info.v_filter_2 = -1;
884         itv->yuv_info.h_filter = -1;
885
886         /* Set some valid size info */
887         itv->yuv_info.osd_x_offset = read_reg(0x02a04) & 0x00000FFF;
888         itv->yuv_info.osd_y_offset = (read_reg(0x02a04) >> 16) & 0x00000FFF;
889
890         /* Bit 2 of reg 2878 indicates current decoder output format
891            0 : NTSC    1 : PAL */
892         if (read_reg(0x2878) & 4)
893                 itv->yuv_info.decode_height = 576;
894         else
895                 itv->yuv_info.decode_height = 480;
896
897         /* If no visible size set, assume full size */
898         if (!itv->yuv_info.osd_vis_w) itv->yuv_info.osd_vis_w = 720 - itv->yuv_info.osd_x_offset;
899         if (!itv->yuv_info.osd_vis_h) itv->yuv_info.osd_vis_h = itv->yuv_info.decode_height - itv->yuv_info.osd_y_offset;
900
901         /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */
902         itv->yuv_info.blanking_ptr = kzalloc(720*16,GFP_KERNEL);
903         if (itv->yuv_info.blanking_ptr) {
904                 itv->yuv_info.blanking_dmaptr = pci_map_single(itv->dev, itv->yuv_info.blanking_ptr, 720*16, PCI_DMA_TODEVICE);
905         }
906         else {
907                 itv->yuv_info.blanking_dmaptr = 0;
908                 IVTV_DEBUG_WARN ("Failed to allocate yuv blanking buffer\n");
909         }
910
911         IVTV_DEBUG_WARN("Enable video output\n");
912         write_reg_sync(0x00108080, 0x2898);
913
914         /* Enable YUV decoder output */
915         write_reg_sync(0x01, IVTV_REG_VDM);
916
917         set_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
918         atomic_set(&itv->yuv_info.next_dma_frame,0);
919 }
920
921 int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
922 {
923         DEFINE_WAIT(wait);
924         int rc = 0;
925         int got_sig = 0;
926         int frame, next_fill_frame, last_fill_frame;
927
928         IVTV_DEBUG_INFO("yuv_prep_frame\n");
929
930         if (atomic_read(&itv->yuv_info.next_dma_frame) == -1) ivtv_yuv_init(itv);
931
932         frame = atomic_read(&itv->yuv_info.next_fill_frame);
933         next_fill_frame = (frame + 1) & 0x3;
934         last_fill_frame = (atomic_read(&itv->yuv_info.next_dma_frame)+1) & 0x3;
935
936         if (next_fill_frame != last_fill_frame && last_fill_frame != frame) {
937                 /* Buffers are full - Overwrite the last frame */
938                 next_fill_frame = frame;
939                 frame = (frame - 1) & 3;
940         }
941
942         /* Take a snapshot of the yuv coordinate information */
943         itv->yuv_info.new_frame_info[frame].src_x = args->src.left;
944         itv->yuv_info.new_frame_info[frame].src_y = args->src.top;
945         itv->yuv_info.new_frame_info[frame].src_w = args->src.width;
946         itv->yuv_info.new_frame_info[frame].src_h = args->src.height;
947         itv->yuv_info.new_frame_info[frame].dst_x = args->dst.left;
948         itv->yuv_info.new_frame_info[frame].dst_y = args->dst.top;
949         itv->yuv_info.new_frame_info[frame].dst_w = args->dst.width;
950         itv->yuv_info.new_frame_info[frame].dst_h = args->dst.height;
951         itv->yuv_info.new_frame_info[frame].tru_x = args->dst.left;
952         itv->yuv_info.new_frame_info[frame].tru_w = args->src_width;
953         itv->yuv_info.new_frame_info[frame].tru_h = args->src_height;
954
955         /* Are we going to offset the Y plane */
956         if (args->src.height + args->src.top < 512-16)
957                 itv->yuv_info.new_frame_info[frame].offset_y = 1;
958         else
959                 itv->yuv_info.new_frame_info[frame].offset_y = 0;
960
961         /* Snapshot the osd pan info */
962         itv->yuv_info.new_frame_info[frame].pan_x = itv->yuv_info.osd_x_pan;
963         itv->yuv_info.new_frame_info[frame].pan_y = itv->yuv_info.osd_y_pan;
964         itv->yuv_info.new_frame_info[frame].vis_w = itv->yuv_info.osd_vis_w;
965         itv->yuv_info.new_frame_info[frame].vis_h = itv->yuv_info.osd_vis_h;
966
967         itv->yuv_info.new_frame_info[frame].update = 0;
968         itv->yuv_info.new_frame_info[frame].interlaced_y = 0;
969         itv->yuv_info.new_frame_info[frame].interlaced_uv = 0;
970
971         if (memcmp (&itv->yuv_info.old_frame_info_args, &itv->yuv_info.new_frame_info[frame],
972             sizeof (itv->yuv_info.new_frame_info[frame]))) {
973                 memcpy(&itv->yuv_info.old_frame_info_args, &itv->yuv_info.new_frame_info[frame], sizeof (itv->yuv_info.old_frame_info_args));
974                 itv->yuv_info.new_frame_info[frame].update = 1;
975 /*              IVTV_DEBUG_YUV ("Requesting register update for frame %d\n",frame); */
976         }
977
978         /* DMA the frame */
979         mutex_lock(&itv->udma.lock);
980
981         if ((rc = ivtv_yuv_prep_user_dma(itv, &itv->udma, args)) != 0) {
982                 mutex_unlock(&itv->udma.lock);
983                 return rc;
984         }
985
986         ivtv_udma_prepare(itv);
987         prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
988         /* if no UDMA is pending and no UDMA is in progress, then the DMA
989         is finished */
990         while (itv->i_flags & (IVTV_F_I_UDMA_PENDING | IVTV_F_I_UDMA)) {
991                 /* don't interrupt if the DMA is in progress but break off
992                 a still pending DMA. */
993                 got_sig = signal_pending(current);
994                 if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags))
995                         break;
996                 got_sig = 0;
997                 schedule();
998         }
999         finish_wait(&itv->dma_waitq, &wait);
1000
1001         /* Unmap Last DMA Xfer */
1002         ivtv_udma_unmap(itv);
1003
1004         if (got_sig) {
1005                 IVTV_DEBUG_INFO("User stopped YUV UDMA\n");
1006                 mutex_unlock(&itv->udma.lock);
1007                 return -EINTR;
1008         }
1009
1010         atomic_set(&itv->yuv_info.next_fill_frame, next_fill_frame);
1011
1012         mutex_unlock(&itv->udma.lock);
1013         return rc;
1014 }
1015
1016 void ivtv_yuv_close(struct ivtv *itv)
1017 {
1018         int h_filter, v_filter_1, v_filter_2;
1019
1020         IVTV_DEBUG_YUV("ivtv_yuv_close\n");
1021         ivtv_waitq(&itv->vsync_waitq);
1022
1023         atomic_set(&itv->yuv_info.next_dma_frame, -1);
1024         atomic_set(&itv->yuv_info.next_fill_frame, 0);
1025
1026         /* Reset registers we have changed so mpeg playback works */
1027
1028         /* If we fully restore this register, the display may remain active.
1029            Restore, but set one bit to blank the video. Firmware will always
1030            clear this bit when needed, so not a problem. */
1031         write_reg(itv->yuv_info.reg_2898 | 0x01000000, 0x2898);
1032
1033         write_reg(itv->yuv_info.reg_2834, 0x02834);
1034         write_reg(itv->yuv_info.reg_2838, 0x02838);
1035         write_reg(itv->yuv_info.reg_283c, 0x0283c);
1036         write_reg(itv->yuv_info.reg_2840, 0x02840);
1037         write_reg(itv->yuv_info.reg_2844, 0x02844);
1038         write_reg(itv->yuv_info.reg_2848, 0x02848);
1039         write_reg(itv->yuv_info.reg_2854, 0x02854);
1040         write_reg(itv->yuv_info.reg_285c, 0x0285c);
1041         write_reg(itv->yuv_info.reg_2864, 0x02864);
1042         write_reg(itv->yuv_info.reg_2870, 0x02870);
1043         write_reg(itv->yuv_info.reg_2874, 0x02874);
1044         write_reg(itv->yuv_info.reg_2890, 0x02890);
1045         write_reg(itv->yuv_info.reg_289c, 0x0289c);
1046
1047         write_reg(itv->yuv_info.reg_2918, 0x02918);
1048         write_reg(itv->yuv_info.reg_291c, 0x0291c);
1049         write_reg(itv->yuv_info.reg_2920, 0x02920);
1050         write_reg(itv->yuv_info.reg_2924, 0x02924);
1051         write_reg(itv->yuv_info.reg_2928, 0x02928);
1052         write_reg(itv->yuv_info.reg_292c, 0x0292c);
1053         write_reg(itv->yuv_info.reg_2930, 0x02930);
1054         write_reg(itv->yuv_info.reg_2934, 0x02934);
1055         write_reg(itv->yuv_info.reg_2938, 0x02938);
1056         write_reg(itv->yuv_info.reg_293c, 0x0293c);
1057         write_reg(itv->yuv_info.reg_2940, 0x02940);
1058         write_reg(itv->yuv_info.reg_2944, 0x02944);
1059         write_reg(itv->yuv_info.reg_2948, 0x02948);
1060         write_reg(itv->yuv_info.reg_294c, 0x0294c);
1061         write_reg(itv->yuv_info.reg_2950, 0x02950);
1062         write_reg(itv->yuv_info.reg_2954, 0x02954);
1063         write_reg(itv->yuv_info.reg_2958, 0x02958);
1064         write_reg(itv->yuv_info.reg_295c, 0x0295c);
1065         write_reg(itv->yuv_info.reg_2960, 0x02960);
1066         write_reg(itv->yuv_info.reg_2964, 0x02964);
1067         write_reg(itv->yuv_info.reg_2968, 0x02968);
1068         write_reg(itv->yuv_info.reg_296c, 0x0296c);
1069         write_reg(itv->yuv_info.reg_2970, 0x02970);
1070
1071         /* Prepare to restore filters */
1072
1073         /* First the horizontal filter */
1074         if ((itv->yuv_info.reg_2834 & 0x0000FFFF) == (itv->yuv_info.reg_2834 >> 16)) {
1075                 /* An exact size match uses filter 0 */
1076                 h_filter = 0;
1077         }
1078         else {
1079                 /* Figure out which filter to use */
1080                 h_filter = ((itv->yuv_info.reg_2834 << 16) / (itv->yuv_info.reg_2834 >> 16)) >> 15;
1081                 h_filter = (h_filter >> 1) + (h_filter & 1);
1082                 /* Only an exact size match can use filter 0. */
1083                 if (h_filter < 1) h_filter = 1;
1084         }
1085
1086         /* Now the vertical filter */
1087         if ((itv->yuv_info.reg_2918 & 0x0000FFFF) == (itv->yuv_info.reg_2918 >> 16)) {
1088                 /* An exact size match uses filter 0/1 */
1089                 v_filter_1 = 0;
1090                 v_filter_2 = 1;
1091         }
1092         else {
1093                 /* Figure out which filter to use */
1094                 v_filter_1 = ((itv->yuv_info.reg_2918 << 16) / (itv->yuv_info.reg_2918 >> 16)) >> 15;
1095                 v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1);
1096                 /* Only an exact size match can use filter 0 */
1097                 if (v_filter_1 == 0) v_filter_1 = 1;
1098                 v_filter_2 = v_filter_1;
1099         }
1100
1101         /* Now restore the filters */
1102         ivtv_yuv_filter (itv,h_filter,v_filter_1,v_filter_2);
1103
1104         /* and clear a few registers */
1105         write_reg(0, 0x02814);
1106         write_reg(0, 0x0282c);
1107         write_reg(0, 0x02904);
1108         write_reg(0, 0x02910);
1109
1110         /* Release the blanking buffer */
1111         if (itv->yuv_info.blanking_ptr) {
1112                 kfree (itv->yuv_info.blanking_ptr);
1113                 itv->yuv_info.blanking_ptr = NULL;
1114                 pci_unmap_single(itv->dev, itv->yuv_info.blanking_dmaptr, 720*16, PCI_DMA_TODEVICE);
1115         }
1116
1117         /* Invalidate the old dimension information */
1118         itv->yuv_info.old_frame_info.src_w = 0;
1119         itv->yuv_info.old_frame_info.src_h = 0;
1120         itv->yuv_info.old_frame_info_args.src_w = 0;
1121         itv->yuv_info.old_frame_info_args.src_h = 0;
1122
1123         /* All done. */
1124         clear_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
1125 }
1126