media: fix integer as NULL pointer warnings
[linux-2.6] / drivers / media / video / ivtv / ivtv-yuv.c
1 /*
2     yuv support
3
4     Copyright (C) 2007  Ian Armstrong <ian@iarmst.demon.co.uk>
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "ivtv-driver.h"
22 #include "ivtv-udma.h"
23 #include "ivtv-yuv.h"
24
25 /* 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         if (itv->yuv_info.track_osd) {
722                 /* The OSD can be moved. Track to it */
723                 f->dst_x += itv->yuv_info.osd_x_offset;
724                 f->dst_y += itv->yuv_info.osd_y_offset;
725         }
726
727         /* Width & height for both src & dst must be even.
728            Same for coordinates. */
729         f->dst_w &= ~1;
730         f->dst_x &= ~1;
731
732         f->src_w += f->src_x & 1;
733         f->src_x &= ~1;
734
735         f->src_w &= ~1;
736         f->dst_w &= ~1;
737
738         f->dst_h &= ~1;
739         f->dst_y &= ~1;
740
741         f->src_h += f->src_y & 1;
742         f->src_y &= ~1;
743
744         f->src_h &= ~1;
745         f->dst_h &= ~1;
746
747         /* Due to rounding, we may have reduced the output size to <1/4 of
748            the source. Check again, but this time just resize. Don't change
749            source coordinates */
750         if (f->dst_w < f->src_w / 4) {
751                 f->src_w &= ~3;
752                 f->dst_w = f->src_w / 4;
753                 f->dst_w += f->dst_w & 1;
754         }
755         if (f->dst_h < f->src_h / 4) {
756                 f->src_h &= ~3;
757                 f->dst_h = f->src_h / 4;
758                 f->dst_h += f->dst_h & 1;
759         }
760
761         /* Check again. If there's nothing to safe to display, stop now */
762         if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 ||
763             (int)f->src_w <= 2 || (int)f->src_h <= 2) {
764                 return IVTV_YUV_UPDATE_INVALID;
765         }
766
767         /* Both x offset & width are linked, so they have to be done together */
768         if ((of->dst_w != f->dst_w) || (of->src_w != f->src_w) ||
769             (of->dst_x != f->dst_x) || (of->src_x != f->src_x) ||
770             (of->pan_x != f->pan_x) || (of->vis_w != f->vis_w)) {
771                 yuv_update |= IVTV_YUV_UPDATE_HORIZONTAL;
772         }
773
774         if ((of->src_h != f->src_h) || (of->dst_h != f->dst_h) ||
775             (of->dst_y != f->dst_y) || (of->src_y != f->src_y) ||
776             (of->pan_y != f->pan_y) || (of->vis_h != f->vis_h) ||
777             (of->lace_mode != f->lace_mode) ||
778             (of->interlaced_y != f->interlaced_y) ||
779             (of->interlaced_uv != f->interlaced_uv)) {
780                 yuv_update |= IVTV_YUV_UPDATE_VERTICAL;
781         }
782
783         return yuv_update;
784 }
785
786 /* Update the scaling register to the requested value */
787 void ivtv_yuv_work_handler(struct ivtv *itv)
788 {
789         struct yuv_playback_info *yi = &itv->yuv_info;
790         struct yuv_frame_info f;
791         int frame = yi->update_frame;
792         u32 yuv_update;
793
794         IVTV_DEBUG_YUV("Update yuv registers for frame %d\n", frame);
795         f = yi->new_frame_info[frame];
796
797         if (yi->track_osd) {
798                 /* Snapshot the osd pan info */
799                 f.pan_x = yi->osd_x_pan;
800                 f.pan_y = yi->osd_y_pan;
801                 f.vis_w = yi->osd_vis_w;
802                 f.vis_h = yi->osd_vis_h;
803         } else {
804                 /* Not tracking the osd, so assume full screen */
805                 f.pan_x = 0;
806                 f.pan_y = 0;
807                 f.vis_w = 720;
808                 f.vis_h = yi->decode_height;
809         }
810
811         /* Calculate the display window coordinates. Exit if nothing left */
812         if (!(yuv_update = ivtv_yuv_window_setup(itv, &f)))
813                 return;
814
815         if (yuv_update & IVTV_YUV_UPDATE_INVALID) {
816                 write_reg(0x01008080, 0x2898);
817         } else if (yuv_update) {
818                 write_reg(0x00108080, 0x2898);
819
820                 if (yuv_update & IVTV_YUV_UPDATE_HORIZONTAL)
821                         ivtv_yuv_handle_horizontal(itv, &f);
822
823                 if (yuv_update & IVTV_YUV_UPDATE_VERTICAL)
824                         ivtv_yuv_handle_vertical(itv, &f);
825         }
826         yi->old_frame_info = f;
827 }
828
829 static void ivtv_yuv_init(struct ivtv *itv)
830 {
831         struct yuv_playback_info *yi = &itv->yuv_info;
832
833         IVTV_DEBUG_YUV("ivtv_yuv_init\n");
834
835         /* Take a snapshot of the current register settings */
836         yi->reg_2834 = read_reg(0x02834);
837         yi->reg_2838 = read_reg(0x02838);
838         yi->reg_283c = read_reg(0x0283c);
839         yi->reg_2840 = read_reg(0x02840);
840         yi->reg_2844 = read_reg(0x02844);
841         yi->reg_2848 = read_reg(0x02848);
842         yi->reg_2854 = read_reg(0x02854);
843         yi->reg_285c = read_reg(0x0285c);
844         yi->reg_2864 = read_reg(0x02864);
845         yi->reg_2870 = read_reg(0x02870);
846         yi->reg_2874 = read_reg(0x02874);
847         yi->reg_2898 = read_reg(0x02898);
848         yi->reg_2890 = read_reg(0x02890);
849
850         yi->reg_289c = read_reg(0x0289c);
851         yi->reg_2918 = read_reg(0x02918);
852         yi->reg_291c = read_reg(0x0291c);
853         yi->reg_2920 = read_reg(0x02920);
854         yi->reg_2924 = read_reg(0x02924);
855         yi->reg_2928 = read_reg(0x02928);
856         yi->reg_292c = read_reg(0x0292c);
857         yi->reg_2930 = read_reg(0x02930);
858         yi->reg_2934 = read_reg(0x02934);
859         yi->reg_2938 = read_reg(0x02938);
860         yi->reg_293c = read_reg(0x0293c);
861         yi->reg_2940 = read_reg(0x02940);
862         yi->reg_2944 = read_reg(0x02944);
863         yi->reg_2948 = read_reg(0x02948);
864         yi->reg_294c = read_reg(0x0294c);
865         yi->reg_2950 = read_reg(0x02950);
866         yi->reg_2954 = read_reg(0x02954);
867         yi->reg_2958 = read_reg(0x02958);
868         yi->reg_295c = read_reg(0x0295c);
869         yi->reg_2960 = read_reg(0x02960);
870         yi->reg_2964 = read_reg(0x02964);
871         yi->reg_2968 = read_reg(0x02968);
872         yi->reg_296c = read_reg(0x0296c);
873         yi->reg_2970 = read_reg(0x02970);
874
875         yi->v_filter_1 = -1;
876         yi->v_filter_2 = -1;
877         yi->h_filter = -1;
878
879         /* Set some valid size info */
880         yi->osd_x_offset = read_reg(0x02a04) & 0x00000FFF;
881         yi->osd_y_offset = (read_reg(0x02a04) >> 16) & 0x00000FFF;
882
883         /* Bit 2 of reg 2878 indicates current decoder output format
884            0 : NTSC    1 : PAL */
885         if (read_reg(0x2878) & 4)
886                 yi->decode_height = 576;
887         else
888                 yi->decode_height = 480;
889
890         if (!itv->osd_info) {
891                 yi->osd_vis_w = 720 - yi->osd_x_offset;
892                 yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
893         } else {
894                 /* If no visible size set, assume full size */
895                 if (!yi->osd_vis_w)
896                         yi->osd_vis_w = 720 - yi->osd_x_offset;
897
898                 if (!yi->osd_vis_h) {
899                         yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
900                 } else if (yi->osd_vis_h + yi->osd_y_offset > yi->decode_height) {
901                         /* If output video standard has changed, requested height may
902                            not be legal */
903                         IVTV_DEBUG_WARN("Clipping yuv output - fb size (%d) exceeds video standard limit (%d)\n",
904                                         yi->osd_vis_h + yi->osd_y_offset,
905                                         yi->decode_height);
906                         yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
907                 }
908         }
909
910         /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */
911         yi->blanking_ptr = kzalloc(720 * 16, GFP_KERNEL);
912         if (yi->blanking_ptr) {
913                 yi->blanking_dmaptr = pci_map_single(itv->dev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE);
914         } else {
915                 yi->blanking_dmaptr = 0;
916                 IVTV_DEBUG_WARN("Failed to allocate yuv blanking buffer\n");
917         }
918
919         /* Enable YUV decoder output */
920         write_reg_sync(0x01, IVTV_REG_VDM);
921
922         set_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
923         atomic_set(&yi->next_dma_frame, 0);
924 }
925
926 /* Get next available yuv buffer on PVR350 */
927 static void ivtv_yuv_next_free(struct ivtv *itv)
928 {
929         int draw, display;
930         struct yuv_playback_info *yi = &itv->yuv_info;
931
932         if (atomic_read(&yi->next_dma_frame) == -1)
933                 ivtv_yuv_init(itv);
934
935         draw = atomic_read(&yi->next_fill_frame);
936         display = atomic_read(&yi->next_dma_frame);
937
938         if (display > draw)
939                 display -= IVTV_YUV_BUFFERS;
940
941         if (draw - display >= yi->max_frames_buffered)
942                 draw = (u8)(draw - 1) % IVTV_YUV_BUFFERS;
943         else
944                 yi->new_frame_info[draw].update = 0;
945
946         yi->draw_frame = draw;
947 }
948
949 /* Set up frame according to ivtv_dma_frame parameters */
950 static void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
951 {
952         struct yuv_playback_info *yi = &itv->yuv_info;
953         u8 frame = yi->draw_frame;
954         u8 last_frame = (u8)(frame - 1) % IVTV_YUV_BUFFERS;
955         struct yuv_frame_info *nf = &yi->new_frame_info[frame];
956         struct yuv_frame_info *of = &yi->new_frame_info[last_frame];
957         int lace_threshold = yi->lace_threshold;
958
959         /* Preserve old update flag in case we're overwriting a queued frame */
960         int update = nf->update;
961
962         /* Take a snapshot of the yuv coordinate information */
963         nf->src_x = args->src.left;
964         nf->src_y = args->src.top;
965         nf->src_w = args->src.width;
966         nf->src_h = args->src.height;
967         nf->dst_x = args->dst.left;
968         nf->dst_y = args->dst.top;
969         nf->dst_w = args->dst.width;
970         nf->dst_h = args->dst.height;
971         nf->tru_x = args->dst.left;
972         nf->tru_w = args->src_width;
973         nf->tru_h = args->src_height;
974
975         /* Are we going to offset the Y plane */
976         nf->offset_y = (nf->tru_h + nf->src_x < 512 - 16) ? 1 : 0;
977
978         nf->update = 0;
979         nf->interlaced_y = 0;
980         nf->interlaced_uv = 0;
981         nf->delay = 0;
982         nf->sync_field = 0;
983         nf->lace_mode = yi->lace_mode & IVTV_YUV_MODE_MASK;
984
985         if (lace_threshold < 0)
986                 lace_threshold = yi->decode_height - 1;
987
988         /* Work out the lace settings */
989         switch (nf->lace_mode) {
990         case IVTV_YUV_MODE_PROGRESSIVE: /* Progressive mode */
991                 nf->interlaced = 0;
992                 if (nf->tru_h < 512 || (nf->tru_h > 576 && nf->tru_h < 1021))
993                         nf->interlaced_y = 0;
994                 else
995                         nf->interlaced_y = 1;
996
997                 if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
998                         nf->interlaced_uv = 0;
999                 else
1000                         nf->interlaced_uv = 1;
1001                 break;
1002
1003         case IVTV_YUV_MODE_AUTO:
1004                 if (nf->tru_h <= lace_threshold || nf->tru_h > 576 || nf->tru_w > 720) {
1005                         nf->interlaced = 0;
1006                         if ((nf->tru_h < 512) ||
1007                             (nf->tru_h > 576 && nf->tru_h < 1021) ||
1008                             (nf->tru_w > 720 && nf->tru_h < 1021))
1009                                 nf->interlaced_y = 0;
1010                         else
1011                                 nf->interlaced_y = 1;
1012                         if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
1013                                 nf->interlaced_uv = 0;
1014                         else
1015                                 nf->interlaced_uv = 1;
1016                 } else {
1017                         nf->interlaced = 1;
1018                         nf->interlaced_y = 1;
1019                         nf->interlaced_uv = 1;
1020                 }
1021                 break;
1022
1023         case IVTV_YUV_MODE_INTERLACED: /* Interlace mode */
1024         default:
1025                 nf->interlaced = 1;
1026                 nf->interlaced_y = 1;
1027                 nf->interlaced_uv = 1;
1028                 break;
1029         }
1030
1031         if (memcmp(&yi->old_frame_info_args, nf, sizeof(*nf))) {
1032                 yi->old_frame_info_args = *nf;
1033                 nf->update = 1;
1034                 IVTV_DEBUG_YUV("Requesting reg update for frame %d\n", frame);
1035         }
1036
1037         nf->update |= update;
1038         nf->sync_field = yi->lace_sync_field;
1039         nf->delay = nf->sync_field != of->sync_field;
1040 }
1041
1042 /* Frame is complete & ready for display */
1043 void ivtv_yuv_frame_complete(struct ivtv *itv)
1044 {
1045         atomic_set(&itv->yuv_info.next_fill_frame,
1046                         (itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS);
1047 }
1048
1049 static int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
1050 {
1051         DEFINE_WAIT(wait);
1052         int rc = 0;
1053         int got_sig = 0;
1054         /* DMA the frame */
1055         mutex_lock(&itv->udma.lock);
1056
1057         if ((rc = ivtv_yuv_prep_user_dma(itv, &itv->udma, args)) != 0) {
1058                 mutex_unlock(&itv->udma.lock);
1059                 return rc;
1060         }
1061
1062         ivtv_udma_prepare(itv);
1063         prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
1064         /* if no UDMA is pending and no UDMA is in progress, then the DMA
1065            is finished */
1066         while (itv->i_flags & (IVTV_F_I_UDMA_PENDING | IVTV_F_I_UDMA)) {
1067                 /* don't interrupt if the DMA is in progress but break off
1068                    a still pending DMA. */
1069                 got_sig = signal_pending(current);
1070                 if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags))
1071                         break;
1072                 got_sig = 0;
1073                 schedule();
1074         }
1075         finish_wait(&itv->dma_waitq, &wait);
1076
1077         /* Unmap Last DMA Xfer */
1078         ivtv_udma_unmap(itv);
1079
1080         if (got_sig) {
1081                 IVTV_DEBUG_INFO("User stopped YUV UDMA\n");
1082                 mutex_unlock(&itv->udma.lock);
1083                 return -EINTR;
1084         }
1085
1086         ivtv_yuv_frame_complete(itv);
1087
1088         mutex_unlock(&itv->udma.lock);
1089         return rc;
1090 }
1091
1092 /* Setup frame according to V4L2 parameters */
1093 void ivtv_yuv_setup_stream_frame(struct ivtv *itv)
1094 {
1095         struct yuv_playback_info *yi = &itv->yuv_info;
1096         struct ivtv_dma_frame dma_args;
1097
1098         ivtv_yuv_next_free(itv);
1099
1100         /* Copy V4L2 parameters to an ivtv_dma_frame struct... */
1101         dma_args.y_source = NULL;
1102         dma_args.uv_source = NULL;
1103         dma_args.src.left = 0;
1104         dma_args.src.top = 0;
1105         dma_args.src.width = yi->v4l2_src_w;
1106         dma_args.src.height = yi->v4l2_src_h;
1107         dma_args.dst = yi->main_rect;
1108         dma_args.src_width = yi->v4l2_src_w;
1109         dma_args.src_height = yi->v4l2_src_h;
1110
1111         /* ... and use the same setup routine as ivtv_yuv_prep_frame */
1112         ivtv_yuv_setup_frame(itv, &dma_args);
1113
1114         if (!itv->dma_data_req_offset)
1115                 itv->dma_data_req_offset = yuv_offset[yi->draw_frame];
1116 }
1117
1118 /* Attempt to dma a frame from a user buffer */
1119 int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void *src)
1120 {
1121         struct yuv_playback_info *yi = &itv->yuv_info;
1122         struct ivtv_dma_frame dma_args;
1123
1124         ivtv_yuv_setup_stream_frame(itv);
1125
1126         /* We only need to supply source addresses for this */
1127         dma_args.y_source = src;
1128         dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31);
1129         return ivtv_yuv_udma_frame(itv, &dma_args);
1130 }
1131
1132 /* IVTV_IOC_DMA_FRAME ioctl handler */
1133 int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
1134 {
1135 /*      IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
1136
1137         ivtv_yuv_next_free(itv);
1138         ivtv_yuv_setup_frame(itv, args);
1139         return ivtv_yuv_udma_frame(itv, args);
1140 }
1141
1142 void ivtv_yuv_close(struct ivtv *itv)
1143 {
1144         struct yuv_playback_info *yi = &itv->yuv_info;
1145         int h_filter, v_filter_1, v_filter_2;
1146
1147         IVTV_DEBUG_YUV("ivtv_yuv_close\n");
1148         ivtv_waitq(&itv->vsync_waitq);
1149
1150         atomic_set(&yi->next_dma_frame, -1);
1151         atomic_set(&yi->next_fill_frame, 0);
1152
1153         /* Reset registers we have changed so mpeg playback works */
1154
1155         /* If we fully restore this register, the display may remain active.
1156            Restore, but set one bit to blank the video. Firmware will always
1157            clear this bit when needed, so not a problem. */
1158         write_reg(yi->reg_2898 | 0x01000000, 0x2898);
1159
1160         write_reg(yi->reg_2834, 0x02834);
1161         write_reg(yi->reg_2838, 0x02838);
1162         write_reg(yi->reg_283c, 0x0283c);
1163         write_reg(yi->reg_2840, 0x02840);
1164         write_reg(yi->reg_2844, 0x02844);
1165         write_reg(yi->reg_2848, 0x02848);
1166         write_reg(yi->reg_2854, 0x02854);
1167         write_reg(yi->reg_285c, 0x0285c);
1168         write_reg(yi->reg_2864, 0x02864);
1169         write_reg(yi->reg_2870, 0x02870);
1170         write_reg(yi->reg_2874, 0x02874);
1171         write_reg(yi->reg_2890, 0x02890);
1172         write_reg(yi->reg_289c, 0x0289c);
1173
1174         write_reg(yi->reg_2918, 0x02918);
1175         write_reg(yi->reg_291c, 0x0291c);
1176         write_reg(yi->reg_2920, 0x02920);
1177         write_reg(yi->reg_2924, 0x02924);
1178         write_reg(yi->reg_2928, 0x02928);
1179         write_reg(yi->reg_292c, 0x0292c);
1180         write_reg(yi->reg_2930, 0x02930);
1181         write_reg(yi->reg_2934, 0x02934);
1182         write_reg(yi->reg_2938, 0x02938);
1183         write_reg(yi->reg_293c, 0x0293c);
1184         write_reg(yi->reg_2940, 0x02940);
1185         write_reg(yi->reg_2944, 0x02944);
1186         write_reg(yi->reg_2948, 0x02948);
1187         write_reg(yi->reg_294c, 0x0294c);
1188         write_reg(yi->reg_2950, 0x02950);
1189         write_reg(yi->reg_2954, 0x02954);
1190         write_reg(yi->reg_2958, 0x02958);
1191         write_reg(yi->reg_295c, 0x0295c);
1192         write_reg(yi->reg_2960, 0x02960);
1193         write_reg(yi->reg_2964, 0x02964);
1194         write_reg(yi->reg_2968, 0x02968);
1195         write_reg(yi->reg_296c, 0x0296c);
1196         write_reg(yi->reg_2970, 0x02970);
1197
1198         /* Prepare to restore filters */
1199
1200         /* First the horizontal filter */
1201         if ((yi->reg_2834 & 0x0000FFFF) == (yi->reg_2834 >> 16)) {
1202                 /* An exact size match uses filter 0 */
1203                 h_filter = 0;
1204         } else {
1205                 /* Figure out which filter to use */
1206                 h_filter = ((yi->reg_2834 << 16) / (yi->reg_2834 >> 16)) >> 15;
1207                 h_filter = (h_filter >> 1) + (h_filter & 1);
1208                 /* Only an exact size match can use filter 0. */
1209                 h_filter += !h_filter;
1210         }
1211
1212         /* Now the vertical filter */
1213         if ((yi->reg_2918 & 0x0000FFFF) == (yi->reg_2918 >> 16)) {
1214                 /* An exact size match uses filter 0/1 */
1215                 v_filter_1 = 0;
1216                 v_filter_2 = 1;
1217         } else {
1218                 /* Figure out which filter to use */
1219                 v_filter_1 = ((yi->reg_2918 << 16) / (yi->reg_2918 >> 16)) >> 15;
1220                 v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1);
1221                 /* Only an exact size match can use filter 0 */
1222                 v_filter_1 += !v_filter_1;
1223                 v_filter_2 = v_filter_1;
1224         }
1225
1226         /* Now restore the filters */
1227         ivtv_yuv_filter(itv, h_filter, v_filter_1, v_filter_2);
1228
1229         /* and clear a few registers */
1230         write_reg(0, 0x02814);
1231         write_reg(0, 0x0282c);
1232         write_reg(0, 0x02904);
1233         write_reg(0, 0x02910);
1234
1235         /* Release the blanking buffer */
1236         if (yi->blanking_ptr) {
1237                 kfree(yi->blanking_ptr);
1238                 yi->blanking_ptr = NULL;
1239                 pci_unmap_single(itv->dev, yi->blanking_dmaptr, 720*16, PCI_DMA_TODEVICE);
1240         }
1241
1242         /* Invalidate the old dimension information */
1243         yi->old_frame_info.src_w = 0;
1244         yi->old_frame_info.src_h = 0;
1245         yi->old_frame_info_args.src_w = 0;
1246         yi->old_frame_info_args.src_h = 0;
1247
1248         /* All done. */
1249         clear_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
1250 }