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