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