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