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