GNU Linux-libre 6.7.9-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], 0);
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], 0);
71         }
72
73         if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) {
74                 int rc = -EFAULT;
75
76                 if (y_pages == y_dma.page_count) {
77                         IVTV_DEBUG_WARN
78                                 ("failed to map uv user pages, returned %d expecting %d\n",
79                                  uv_pages, uv_dma.page_count);
80
81                         if (uv_pages >= 0) {
82                                 unpin_user_pages(&dma->map[y_pages], uv_pages);
83                                 rc = -EFAULT;
84                         } else {
85                                 rc = uv_pages;
86                         }
87                 } else {
88                         IVTV_DEBUG_WARN
89                                 ("failed to map y user pages, returned %d expecting %d\n",
90                                  y_pages, y_dma.page_count);
91                 }
92                 if (y_pages >= 0) {
93                         unpin_user_pages(dma->map, y_pages);
94                         /*
95                          * Inherit the -EFAULT from rc's
96                          * initialization, but allow it to be
97                          * overridden by uv_pages above if it was an
98                          * actual errno.
99                          */
100                 } else {
101                         rc = y_pages;
102                 }
103                 return rc;
104         }
105
106         dma->page_count = y_pages + uv_pages;
107
108         /* Fill & map SG List */
109         if (ivtv_udma_fill_sg_list (dma, &uv_dma, ivtv_udma_fill_sg_list (dma, &y_dma, 0)) < 0) {
110                 IVTV_DEBUG_WARN("could not allocate bounce buffers for highmem userspace buffers\n");
111                 unpin_user_pages(dma->map, dma->page_count);
112                 dma->page_count = 0;
113                 return -ENOMEM;
114         }
115         dma->SG_length = dma_map_sg(&itv->pdev->dev, dma->SGlist,
116                                     dma->page_count, DMA_TO_DEVICE);
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 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 = dma_map_single(&itv->pdev->dev,
924                                                      yi->blanking_ptr,
925                                                      720 * 16, DMA_TO_DEVICE);
926         } else {
927                 yi->blanking_dmaptr = 0;
928                 IVTV_DEBUG_WARN("Failed to allocate yuv blanking buffer\n");
929         }
930
931         /* Enable YUV decoder output */
932         write_reg_sync(0x01, IVTV_REG_VDM);
933
934         set_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
935         atomic_set(&yi->next_dma_frame, 0);
936 }
937
938 /* Get next available yuv buffer on PVR350 */
939 static void ivtv_yuv_next_free(struct ivtv *itv)
940 {
941         int draw, display;
942         struct yuv_playback_info *yi = &itv->yuv_info;
943
944         if (atomic_read(&yi->next_dma_frame) == -1)
945                 ivtv_yuv_init(itv);
946
947         draw = atomic_read(&yi->next_fill_frame);
948         display = atomic_read(&yi->next_dma_frame);
949
950         if (display > draw)
951                 display -= IVTV_YUV_BUFFERS;
952
953         if (draw - display >= yi->max_frames_buffered)
954                 draw = (u8)(draw - 1) % IVTV_YUV_BUFFERS;
955         else
956                 yi->new_frame_info[draw].update = 0;
957
958         yi->draw_frame = draw;
959 }
960
961 /* Set up frame according to ivtv_dma_frame parameters */
962 static void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
963 {
964         struct yuv_playback_info *yi = &itv->yuv_info;
965         u8 frame = yi->draw_frame;
966         u8 last_frame = (u8)(frame - 1) % IVTV_YUV_BUFFERS;
967         struct yuv_frame_info *nf = &yi->new_frame_info[frame];
968         struct yuv_frame_info *of = &yi->new_frame_info[last_frame];
969         int lace_threshold = yi->lace_threshold;
970
971         /* Preserve old update flag in case we're overwriting a queued frame */
972         int update = nf->update;
973
974         /* Take a snapshot of the yuv coordinate information */
975         nf->src_x = args->src.left;
976         nf->src_y = args->src.top;
977         nf->src_w = args->src.width;
978         nf->src_h = args->src.height;
979         nf->dst_x = args->dst.left;
980         nf->dst_y = args->dst.top;
981         nf->dst_w = args->dst.width;
982         nf->dst_h = args->dst.height;
983         nf->tru_x = args->dst.left;
984         nf->tru_w = args->src_width;
985         nf->tru_h = args->src_height;
986
987         /* Are we going to offset the Y plane */
988         nf->offset_y = (nf->tru_h + nf->src_x < 512 - 16) ? 1 : 0;
989
990         nf->update = 0;
991         nf->interlaced_y = 0;
992         nf->interlaced_uv = 0;
993         nf->delay = 0;
994         nf->sync_field = 0;
995         nf->lace_mode = yi->lace_mode & IVTV_YUV_MODE_MASK;
996
997         if (lace_threshold < 0)
998                 lace_threshold = yi->decode_height - 1;
999
1000         /* Work out the lace settings */
1001         switch (nf->lace_mode) {
1002         case IVTV_YUV_MODE_PROGRESSIVE: /* Progressive mode */
1003                 nf->interlaced = 0;
1004                 if (nf->tru_h < 512 || (nf->tru_h > 576 && nf->tru_h < 1021))
1005                         nf->interlaced_y = 0;
1006                 else
1007                         nf->interlaced_y = 1;
1008
1009                 if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
1010                         nf->interlaced_uv = 0;
1011                 else
1012                         nf->interlaced_uv = 1;
1013                 break;
1014
1015         case IVTV_YUV_MODE_AUTO:
1016                 if (nf->tru_h <= lace_threshold || nf->tru_h > 576 || nf->tru_w > 720) {
1017                         nf->interlaced = 0;
1018                         if ((nf->tru_h < 512) ||
1019                             (nf->tru_h > 576 && nf->tru_h < 1021) ||
1020                             (nf->tru_w > 720 && nf->tru_h < 1021))
1021                                 nf->interlaced_y = 0;
1022                         else
1023                                 nf->interlaced_y = 1;
1024                         if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
1025                                 nf->interlaced_uv = 0;
1026                         else
1027                                 nf->interlaced_uv = 1;
1028                 } else {
1029                         nf->interlaced = 1;
1030                         nf->interlaced_y = 1;
1031                         nf->interlaced_uv = 1;
1032                 }
1033                 break;
1034
1035         case IVTV_YUV_MODE_INTERLACED: /* Interlace mode */
1036         default:
1037                 nf->interlaced = 1;
1038                 nf->interlaced_y = 1;
1039                 nf->interlaced_uv = 1;
1040                 break;
1041         }
1042
1043         if (memcmp(&yi->old_frame_info_args, nf, sizeof(*nf))) {
1044                 yi->old_frame_info_args = *nf;
1045                 nf->update = 1;
1046                 IVTV_DEBUG_YUV("Requesting reg update for frame %d\n", frame);
1047         }
1048
1049         nf->update |= update;
1050         nf->sync_field = yi->lace_sync_field;
1051         nf->delay = nf->sync_field != of->sync_field;
1052 }
1053
1054 /* Frame is complete & ready for display */
1055 void ivtv_yuv_frame_complete(struct ivtv *itv)
1056 {
1057         atomic_set(&itv->yuv_info.next_fill_frame,
1058                         (itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS);
1059 }
1060
1061 static int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
1062 {
1063         DEFINE_WAIT(wait);
1064         int rc = 0;
1065         int got_sig = 0;
1066         /* DMA the frame */
1067         mutex_lock(&itv->udma.lock);
1068
1069         if ((rc = ivtv_yuv_prep_user_dma(itv, &itv->udma, args)) != 0) {
1070                 mutex_unlock(&itv->udma.lock);
1071                 return rc;
1072         }
1073
1074         ivtv_udma_prepare(itv);
1075         prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
1076         /* if no UDMA is pending and no UDMA is in progress, then the DMA
1077            is finished */
1078         while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) ||
1079                test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
1080                 /* don't interrupt if the DMA is in progress but break off
1081                    a still pending DMA. */
1082                 got_sig = signal_pending(current);
1083                 if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags))
1084                         break;
1085                 got_sig = 0;
1086                 schedule();
1087         }
1088         finish_wait(&itv->dma_waitq, &wait);
1089
1090         /* Unmap Last DMA Xfer */
1091         ivtv_udma_unmap(itv);
1092
1093         if (got_sig) {
1094                 IVTV_DEBUG_INFO("User stopped YUV UDMA\n");
1095                 mutex_unlock(&itv->udma.lock);
1096                 return -EINTR;
1097         }
1098
1099         ivtv_yuv_frame_complete(itv);
1100
1101         mutex_unlock(&itv->udma.lock);
1102         return rc;
1103 }
1104
1105 /* Setup frame according to V4L2 parameters */
1106 void ivtv_yuv_setup_stream_frame(struct ivtv *itv)
1107 {
1108         struct yuv_playback_info *yi = &itv->yuv_info;
1109         struct ivtv_dma_frame dma_args;
1110
1111         ivtv_yuv_next_free(itv);
1112
1113         /* Copy V4L2 parameters to an ivtv_dma_frame struct... */
1114         dma_args.y_source = NULL;
1115         dma_args.uv_source = NULL;
1116         dma_args.src.left = 0;
1117         dma_args.src.top = 0;
1118         dma_args.src.width = yi->v4l2_src_w;
1119         dma_args.src.height = yi->v4l2_src_h;
1120         dma_args.dst = yi->main_rect;
1121         dma_args.src_width = yi->v4l2_src_w;
1122         dma_args.src_height = yi->v4l2_src_h;
1123
1124         /* ... and use the same setup routine as ivtv_yuv_prep_frame */
1125         ivtv_yuv_setup_frame(itv, &dma_args);
1126
1127         if (!itv->dma_data_req_offset)
1128                 itv->dma_data_req_offset = yuv_offset[yi->draw_frame];
1129 }
1130
1131 /* Attempt to dma a frame from a user buffer */
1132 int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src)
1133 {
1134         struct yuv_playback_info *yi = &itv->yuv_info;
1135         struct ivtv_dma_frame dma_args;
1136         int res;
1137
1138         ivtv_yuv_setup_stream_frame(itv);
1139
1140         /* We only need to supply source addresses for this */
1141         dma_args.y_source = src;
1142         dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31);
1143         /* Wait for frame DMA. Note that serialize_lock is locked,
1144            so to allow other processes to access the driver while
1145            we are waiting unlock first and later lock again. */
1146         mutex_unlock(&itv->serialize_lock);
1147         res = ivtv_yuv_udma_frame(itv, &dma_args);
1148         mutex_lock(&itv->serialize_lock);
1149         return res;
1150 }
1151
1152 /* IVTV_IOC_DMA_FRAME ioctl handler */
1153 int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
1154 {
1155         int res;
1156
1157 /*      IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
1158         ivtv_yuv_next_free(itv);
1159         ivtv_yuv_setup_frame(itv, args);
1160         /* Wait for frame DMA. Note that serialize_lock is locked,
1161            so to allow other processes to access the driver while
1162            we are waiting unlock first and later lock again. */
1163         mutex_unlock(&itv->serialize_lock);
1164         res = ivtv_yuv_udma_frame(itv, args);
1165         mutex_lock(&itv->serialize_lock);
1166         return res;
1167 }
1168
1169 void ivtv_yuv_close(struct ivtv *itv)
1170 {
1171         struct yuv_playback_info *yi = &itv->yuv_info;
1172         int h_filter, v_filter_1, v_filter_2;
1173
1174         IVTV_DEBUG_YUV("ivtv_yuv_close\n");
1175         mutex_unlock(&itv->serialize_lock);
1176         ivtv_waitq(&itv->vsync_waitq);
1177         mutex_lock(&itv->serialize_lock);
1178
1179         yi->running = 0;
1180         atomic_set(&yi->next_dma_frame, -1);
1181         atomic_set(&yi->next_fill_frame, 0);
1182
1183         /* Reset registers we have changed so mpeg playback works */
1184
1185         /* If we fully restore this register, the display may remain active.
1186            Restore, but set one bit to blank the video. Firmware will always
1187            clear this bit when needed, so not a problem. */
1188         write_reg(yi->reg_2898 | 0x01000000, 0x2898);
1189
1190         write_reg(yi->reg_2834, 0x02834);
1191         write_reg(yi->reg_2838, 0x02838);
1192         write_reg(yi->reg_283c, 0x0283c);
1193         write_reg(yi->reg_2840, 0x02840);
1194         write_reg(yi->reg_2844, 0x02844);
1195         write_reg(yi->reg_2848, 0x02848);
1196         write_reg(yi->reg_2854, 0x02854);
1197         write_reg(yi->reg_285c, 0x0285c);
1198         write_reg(yi->reg_2864, 0x02864);
1199         write_reg(yi->reg_2870, 0x02870);
1200         write_reg(yi->reg_2874, 0x02874);
1201         write_reg(yi->reg_2890, 0x02890);
1202         write_reg(yi->reg_289c, 0x0289c);
1203
1204         write_reg(yi->reg_2918, 0x02918);
1205         write_reg(yi->reg_291c, 0x0291c);
1206         write_reg(yi->reg_2920, 0x02920);
1207         write_reg(yi->reg_2924, 0x02924);
1208         write_reg(yi->reg_2928, 0x02928);
1209         write_reg(yi->reg_292c, 0x0292c);
1210         write_reg(yi->reg_2930, 0x02930);
1211         write_reg(yi->reg_2934, 0x02934);
1212         write_reg(yi->reg_2938, 0x02938);
1213         write_reg(yi->reg_293c, 0x0293c);
1214         write_reg(yi->reg_2940, 0x02940);
1215         write_reg(yi->reg_2944, 0x02944);
1216         write_reg(yi->reg_2948, 0x02948);
1217         write_reg(yi->reg_294c, 0x0294c);
1218         write_reg(yi->reg_2950, 0x02950);
1219         write_reg(yi->reg_2954, 0x02954);
1220         write_reg(yi->reg_2958, 0x02958);
1221         write_reg(yi->reg_295c, 0x0295c);
1222         write_reg(yi->reg_2960, 0x02960);
1223         write_reg(yi->reg_2964, 0x02964);
1224         write_reg(yi->reg_2968, 0x02968);
1225         write_reg(yi->reg_296c, 0x0296c);
1226         write_reg(yi->reg_2970, 0x02970);
1227
1228         /* Prepare to restore filters */
1229
1230         /* First the horizontal filter */
1231         if ((yi->reg_2834 & 0x0000FFFF) == (yi->reg_2834 >> 16)) {
1232                 /* An exact size match uses filter 0 */
1233                 h_filter = 0;
1234         } else {
1235                 /* Figure out which filter to use */
1236                 h_filter = ((yi->reg_2834 << 16) / (yi->reg_2834 >> 16)) >> 15;
1237                 h_filter = (h_filter >> 1) + (h_filter & 1);
1238                 /* Only an exact size match can use filter 0. */
1239                 h_filter += !h_filter;
1240         }
1241
1242         /* Now the vertical filter */
1243         if ((yi->reg_2918 & 0x0000FFFF) == (yi->reg_2918 >> 16)) {
1244                 /* An exact size match uses filter 0/1 */
1245                 v_filter_1 = 0;
1246                 v_filter_2 = 1;
1247         } else {
1248                 /* Figure out which filter to use */
1249                 v_filter_1 = ((yi->reg_2918 << 16) / (yi->reg_2918 >> 16)) >> 15;
1250                 v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1);
1251                 /* Only an exact size match can use filter 0 */
1252                 v_filter_1 += !v_filter_1;
1253                 v_filter_2 = v_filter_1;
1254         }
1255
1256         /* Now restore the filters */
1257         ivtv_yuv_filter(itv, h_filter, v_filter_1, v_filter_2);
1258
1259         /* and clear a few registers */
1260         write_reg(0, 0x02814);
1261         write_reg(0, 0x0282c);
1262         write_reg(0, 0x02904);
1263         write_reg(0, 0x02910);
1264
1265         /* Release the blanking buffer */
1266         if (yi->blanking_ptr) {
1267                 kfree(yi->blanking_ptr);
1268                 yi->blanking_ptr = NULL;
1269                 dma_unmap_single(&itv->pdev->dev, yi->blanking_dmaptr,
1270                                  720 * 16, DMA_TO_DEVICE);
1271         }
1272
1273         /* Invalidate the old dimension information */
1274         yi->old_frame_info.src_w = 0;
1275         yi->old_frame_info.src_h = 0;
1276         yi->old_frame_info_args.src_w = 0;
1277         yi->old_frame_info_args.src_h = 0;
1278
1279         /* All done. */
1280         clear_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
1281 }