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