4 Copyright (C) 2007 Ian Armstrong <ian@iarmst.demon.co.uk>
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.
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.
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
21 #include "ivtv-driver.h"
22 #include "ivtv-udma.h"
25 /* YUV buffer offsets */
26 const u32 yuv_offset
[IVTV_YUV_BUFFERS
] = {
37 static int ivtv_yuv_prep_user_dma(struct ivtv
*itv
, struct ivtv_user_dma
*dma
,
38 struct ivtv_dma_frame
*args
)
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
];
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
;
50 y_buffer_offset
= IVTV_DECODER_OFFSET
+ yuv_offset
[frame
];
51 uv_buffer_offset
= y_buffer_offset
+ IVTV_YUV_BUFFER_UV_OFFSET
;
53 y_decode_height
= uv_decode_height
= f
->src_h
+ f
->src_y
;
56 y_buffer_offset
+= 720 * 16;
58 if (y_decode_height
& 15)
59 y_decode_height
= (y_decode_height
+ 16) & ~15;
61 if (uv_decode_height
& 31)
62 uv_decode_height
= (uv_decode_height
+ 32) & ~31;
64 y_size
= 720 * y_decode_height
;
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
);
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
);
77 /* Get user pages for DMA Xfer */
78 y_pages
= get_user_pages_unlocked(y_dma
.uaddr
,
79 y_dma
.page_count
, 0, 1, &dma
->map
[0]);
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_unlocked(uv_dma
.uaddr
,
83 uv_dma
.page_count
, 0, 1, &dma
->map
[y_pages
]);
86 if (y_pages
!= y_dma
.page_count
|| uv_pages
!= uv_dma
.page_count
) {
89 if (y_pages
== y_dma
.page_count
) {
91 ("failed to map uv user pages, returned %d "
92 "expecting %d\n", uv_pages
, uv_dma
.page_count
);
95 for (i
= 0; i
< uv_pages
; i
++)
96 put_page(dma
->map
[y_pages
+ i
]);
103 ("failed to map y user pages, returned %d "
104 "expecting %d\n", y_pages
, y_dma
.page_count
);
107 for (i
= 0; i
< y_pages
; i
++)
108 put_page(dma
->map
[i
]);
110 * Inherit the -EFAULT from rc's
111 * initialization, but allow it to be
112 * overriden by uv_pages above if it was an
121 dma
->page_count
= y_pages
+ uv_pages
;
123 /* Fill & map SG List */
124 if (ivtv_udma_fill_sg_list (dma
, &uv_dma
, ivtv_udma_fill_sg_list (dma
, &y_dma
, 0)) < 0) {
125 IVTV_DEBUG_WARN("could not allocate bounce buffers for highmem userspace buffers\n");
126 for (i
= 0; i
< dma
->page_count
; i
++) {
127 put_page(dma
->map
[i
]);
132 dma
->SG_length
= pci_map_sg(itv
->pdev
, dma
->SGlist
, dma
->page_count
, PCI_DMA_TODEVICE
);
134 /* Fill SG Array with new values */
135 ivtv_udma_fill_sg_array(dma
, y_buffer_offset
, uv_buffer_offset
, y_size
);
137 /* If we've offset the y plane, ensure top area is blanked */
138 if (f
->offset_y
&& yi
->blanking_dmaptr
) {
139 dma
->SGarray
[dma
->SG_length
].size
= cpu_to_le32(720*16);
140 dma
->SGarray
[dma
->SG_length
].src
= cpu_to_le32(yi
->blanking_dmaptr
);
141 dma
->SGarray
[dma
->SG_length
].dst
= cpu_to_le32(IVTV_DECODER_OFFSET
+ yuv_offset
[frame
]);
145 /* Tag SG Array with Interrupt Bit */
146 dma
->SGarray
[dma
->SG_length
- 1].size
|= cpu_to_le32(0x80000000);
148 ivtv_udma_sync_for_device(itv
);
152 /* We rely on a table held in the firmware - Quick check. */
153 int ivtv_yuv_filter_check(struct ivtv
*itv
)
157 for (i
= 0, y
= 16, uv
= 4; i
< 16; i
++, y
+= 24, uv
+= 12) {
158 if ((read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET
+ y
) != i
<< 16) ||
159 (read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET
+ uv
) != i
<< 16)) {
160 IVTV_WARN ("YUV filter table not found in firmware.\n");
167 static void ivtv_yuv_filter(struct ivtv
*itv
, int h_filter
, int v_filter_1
, int v_filter_2
)
171 /* If any filter is -1, then don't update it */
175 i
= IVTV_YUV_HORIZONTAL_FILTER_OFFSET
+ (h_filter
* 384);
176 for (line
= 0; line
< 16; line
++) {
177 write_reg(read_dec(i
), 0x02804);
178 write_reg(read_dec(i
), 0x0281c);
180 write_reg(read_dec(i
), 0x02808);
181 write_reg(read_dec(i
), 0x02820);
183 write_reg(read_dec(i
), 0x0280c);
184 write_reg(read_dec(i
), 0x02824);
186 write_reg(read_dec(i
), 0x02810);
187 write_reg(read_dec(i
), 0x02828);
189 write_reg(read_dec(i
), 0x02814);
190 write_reg(read_dec(i
), 0x0282c);
192 write_reg(0, 0x02818);
193 write_reg(0, 0x02830);
195 IVTV_DEBUG_YUV("h_filter -> %d\n", h_filter
);
198 if (v_filter_1
> -1) {
201 i
= IVTV_YUV_VERTICAL_FILTER_OFFSET
+ (v_filter_1
* 192);
202 for (line
= 0; line
< 16; line
++) {
203 write_reg(read_dec(i
), 0x02900);
205 write_reg(read_dec(i
), 0x02904);
207 write_reg(0, 0x02908);
209 IVTV_DEBUG_YUV("v_filter_1 -> %d\n", v_filter_1
);
212 if (v_filter_2
> -1) {
215 i
= IVTV_YUV_VERTICAL_FILTER_OFFSET
+ (v_filter_2
* 192);
216 for (line
= 0; line
< 16; line
++) {
217 write_reg(read_dec(i
), 0x0290c);
219 write_reg(read_dec(i
), 0x02910);
221 write_reg(0, 0x02914);
223 IVTV_DEBUG_YUV("v_filter_2 -> %d\n", v_filter_2
);
227 static void ivtv_yuv_handle_horizontal(struct ivtv
*itv
, struct yuv_frame_info
*f
)
229 struct yuv_playback_info
*yi
= &itv
->yuv_info
;
230 u32 reg_2834
, reg_2838
, reg_283c
;
231 u32 reg_2844
, reg_2854
, reg_285c
;
232 u32 reg_2864
, reg_2874
, reg_2890
;
233 u32 reg_2870
, reg_2870_base
, reg_2870_offset
;
239 ("Adjust to width %d src_w %d dst_w %d src_x %d dst_x %d\n",
240 f
->tru_w
, f
->src_w
, f
->dst_w
, f
->src_x
, f
->dst_x
);
242 /* How wide is the src image */
243 x_cutoff
= f
->src_w
+ f
->src_x
;
245 /* Set the display width */
249 /* Set the display position */
252 /* Index into the image horizontally */
255 /* 2870 is normally fudged to align video coords with osd coords.
256 If running full screen, it causes an unwanted left shift
257 Remove the fudge if we almost fill the screen.
258 Gradually adjust the offset to avoid the video 'snapping'
259 left/right if it gets dragged through this region.
260 Only do this if osd is full width. */
261 if (f
->vis_w
== 720) {
262 if ((f
->tru_x
- f
->pan_x
> -1) && (f
->tru_x
- f
->pan_x
<= 40) && (f
->dst_w
>= 680))
263 reg_2870
= 10 - (f
->tru_x
- f
->pan_x
) / 4;
264 else if ((f
->tru_x
- f
->pan_x
< 0) && (f
->tru_x
- f
->pan_x
>= -20) && (f
->dst_w
>= 660))
265 reg_2870
= (10 + (f
->tru_x
- f
->pan_x
) / 2);
267 if (f
->dst_w
>= f
->src_w
)
268 reg_2870
= reg_2870
<< 16 | reg_2870
;
270 reg_2870
= ((reg_2870
& ~1) << 15) | (reg_2870
& ~1);
273 if (f
->dst_w
< f
->src_w
)
274 reg_2870
= 0x000d000e - reg_2870
;
276 reg_2870
= 0x0012000e - reg_2870
;
278 /* We're also using 2870 to shift the image left (src_x & negative dst_x) */
279 reg_2870_offset
= (f
->src_x
* ((f
->dst_w
<< 21) / f
->src_w
)) >> 19;
281 if (f
->dst_w
>= f
->src_w
) {
283 master_width
= (f
->src_w
* 0x00200000) / (f
->dst_w
);
284 if (master_width
* f
->dst_w
!= f
->src_w
* 0x00200000)
286 reg_2834
= (reg_2834
<< 16) | x_cutoff
;
287 reg_2838
= (reg_2838
<< 16) | x_cutoff
;
288 reg_283c
= master_width
>> 2;
289 reg_2844
= master_width
>> 2;
290 reg_2854
= master_width
;
291 reg_285c
= master_width
>> 1;
292 reg_2864
= master_width
>> 1;
294 /* We also need to factor in the scaling
295 (src_w - dst_w) / (src_w / 4) */
296 if (f
->dst_w
> f
->src_w
)
297 reg_2870_base
= ((f
->dst_w
- f
->src_w
)<<16) / (f
->src_w
<<14);
301 reg_2870
+= (((reg_2870_offset
<< 14) & 0xFFFF0000) | reg_2870_offset
>> 2) + (reg_2870_base
<< 17 | reg_2870_base
);
303 } else if (f
->dst_w
< f
->src_w
/ 2) {
304 master_width
= (f
->src_w
* 0x00080000) / f
->dst_w
;
305 if (master_width
* f
->dst_w
!= f
->src_w
* 0x00080000)
307 reg_2834
= (reg_2834
<< 16) | x_cutoff
;
308 reg_2838
= (reg_2838
<< 16) | x_cutoff
;
309 reg_283c
= master_width
>> 2;
310 reg_2844
= master_width
>> 1;
311 reg_2854
= master_width
;
312 reg_285c
= master_width
>> 1;
313 reg_2864
= master_width
>> 1;
314 reg_2870
+= ((reg_2870_offset
<< 15) & 0xFFFF0000) | reg_2870_offset
;
315 reg_2870
+= (5 - (((f
->src_w
+ f
->src_w
/ 2) - 1) / f
->dst_w
)) << 16;
316 reg_2874
= 0x00000012;
318 master_width
= (f
->src_w
* 0x00100000) / f
->dst_w
;
319 if (master_width
* f
->dst_w
!= f
->src_w
* 0x00100000)
321 reg_2834
= (reg_2834
<< 16) | x_cutoff
;
322 reg_2838
= (reg_2838
<< 16) | x_cutoff
;
323 reg_283c
= master_width
>> 2;
324 reg_2844
= master_width
>> 1;
325 reg_2854
= master_width
;
326 reg_285c
= master_width
>> 1;
327 reg_2864
= master_width
>> 1;
328 reg_2870
+= ((reg_2870_offset
<< 14) & 0xFFFF0000) | reg_2870_offset
>> 1;
329 reg_2870
+= (5 - (((f
->src_w
* 3) - 1) / f
->dst_w
)) << 16;
330 reg_2874
= 0x00000001;
333 /* Select the horizontal filter */
334 if (f
->src_w
== f
->dst_w
) {
335 /* An exact size match uses filter 0 */
338 /* Figure out which filter to use */
339 h_filter
= ((f
->src_w
<< 16) / f
->dst_w
) >> 15;
340 h_filter
= (h_filter
>> 1) + (h_filter
& 1);
341 /* Only an exact size match can use filter 0 */
342 h_filter
+= !h_filter
;
345 write_reg(reg_2834
, 0x02834);
346 write_reg(reg_2838
, 0x02838);
347 IVTV_DEBUG_YUV("Update reg 0x2834 %08x->%08x 0x2838 %08x->%08x\n",
348 yi
->reg_2834
, reg_2834
, yi
->reg_2838
, reg_2838
);
350 write_reg(reg_283c
, 0x0283c);
351 write_reg(reg_2844
, 0x02844);
353 IVTV_DEBUG_YUV("Update reg 0x283c %08x->%08x 0x2844 %08x->%08x\n",
354 yi
->reg_283c
, reg_283c
, yi
->reg_2844
, reg_2844
);
356 write_reg(0x00080514, 0x02840);
357 write_reg(0x00100514, 0x02848);
358 IVTV_DEBUG_YUV("Update reg 0x2840 %08x->%08x 0x2848 %08x->%08x\n",
359 yi
->reg_2840
, 0x00080514, yi
->reg_2848
, 0x00100514);
361 write_reg(reg_2854
, 0x02854);
362 IVTV_DEBUG_YUV("Update reg 0x2854 %08x->%08x \n",
363 yi
->reg_2854
, reg_2854
);
365 write_reg(reg_285c
, 0x0285c);
366 write_reg(reg_2864
, 0x02864);
367 IVTV_DEBUG_YUV("Update reg 0x285c %08x->%08x 0x2864 %08x->%08x\n",
368 yi
->reg_285c
, reg_285c
, yi
->reg_2864
, reg_2864
);
370 write_reg(reg_2874
, 0x02874);
371 IVTV_DEBUG_YUV("Update reg 0x2874 %08x->%08x\n",
372 yi
->reg_2874
, reg_2874
);
374 write_reg(reg_2870
, 0x02870);
375 IVTV_DEBUG_YUV("Update reg 0x2870 %08x->%08x\n",
376 yi
->reg_2870
, reg_2870
);
378 write_reg(reg_2890
, 0x02890);
379 IVTV_DEBUG_YUV("Update reg 0x2890 %08x->%08x\n",
380 yi
->reg_2890
, reg_2890
);
382 /* Only update the filter if we really need to */
383 if (h_filter
!= yi
->h_filter
) {
384 ivtv_yuv_filter(itv
, h_filter
, -1, -1);
385 yi
->h_filter
= h_filter
;
389 static void ivtv_yuv_handle_vertical(struct ivtv
*itv
, struct yuv_frame_info
*f
)
391 struct yuv_playback_info
*yi
= &itv
->yuv_info
;
393 u32 reg_2918
, reg_291c
, reg_2920
, reg_2928
;
394 u32 reg_2930
, reg_2934
, reg_293c
;
395 u32 reg_2940
, reg_2944
, reg_294c
;
396 u32 reg_2950
, reg_2954
, reg_2958
, reg_295c
;
397 u32 reg_2960
, reg_2964
, reg_2968
, reg_296c
;
399 u32 src_major_y
, src_minor_y
;
400 u32 src_major_uv
, src_minor_uv
;
401 u32 reg_2964_base
, reg_2968_base
;
402 int v_filter_1
, v_filter_2
;
405 ("Adjust to height %d src_h %d dst_h %d src_y %d dst_y %d\n",
406 f
->tru_h
, f
->src_h
, f
->dst_h
, f
->src_y
, f
->dst_y
);
408 /* What scaling mode is being used... */
409 IVTV_DEBUG_YUV("Scaling mode Y: %s\n",
410 f
->interlaced_y
? "Interlaced" : "Progressive");
412 IVTV_DEBUG_YUV("Scaling mode UV: %s\n",
413 f
->interlaced_uv
? "Interlaced" : "Progressive");
415 /* What is the source video being treated as... */
416 IVTV_DEBUG_WARN("Source video: %s\n",
417 f
->interlaced
? "Interlaced" : "Progressive");
419 /* We offset into the image using two different index methods, so split
420 the y source coord into two parts. */
422 src_minor_uv
= f
->src_y
;
426 src_major_uv
= f
->src_y
- 8;
429 src_minor_y
= src_minor_uv
;
430 src_major_y
= src_major_uv
;
436 reg_2918
= (f
->dst_h
<< 16) | (f
->src_h
+ src_minor_y
);
438 reg_2918
= (f
->dst_h
<< 16) | ((f
->src_h
+ src_minor_y
) << 1);
440 if (f
->interlaced_uv
)
441 reg_291c
= (f
->dst_h
<< 16) | ((f
->src_h
+ src_minor_uv
) >> 1);
443 reg_291c
= (f
->dst_h
<< 16) | (f
->src_h
+ src_minor_uv
);
445 reg_2964_base
= (src_minor_y
* ((f
->dst_h
<< 16) / f
->src_h
)) >> 14;
446 reg_2968_base
= (src_minor_uv
* ((f
->dst_h
<< 16) / f
->src_h
)) >> 14;
448 if (f
->dst_h
/ 2 >= f
->src_h
&& !f
->interlaced_y
) {
449 master_height
= (f
->src_h
* 0x00400000) / f
->dst_h
;
450 if ((f
->src_h
* 0x00400000) - (master_height
* f
->dst_h
) >= f
->dst_h
/ 2)
452 reg_2920
= master_height
>> 2;
453 reg_2928
= master_height
>> 3;
454 reg_2930
= master_height
;
455 reg_2940
= master_height
>> 1;
458 reg_296c
= 0x00000000;
459 } else if (f
->dst_h
>= f
->src_h
) {
460 master_height
= (f
->src_h
* 0x00400000) / f
->dst_h
;
461 master_height
= (master_height
>> 1) + (master_height
& 1);
462 reg_2920
= master_height
>> 2;
463 reg_2928
= master_height
>> 2;
464 reg_2930
= master_height
;
465 reg_2940
= master_height
>> 1;
466 reg_296c
= 0x00000000;
467 if (f
->interlaced_y
) {
473 if (f
->interlaced_uv
)
476 } else if (f
->dst_h
>= f
->src_h
/ 2) {
477 master_height
= (f
->src_h
* 0x00200000) / f
->dst_h
;
478 master_height
= (master_height
>> 1) + (master_height
& 1);
479 reg_2920
= master_height
>> 2;
480 reg_2928
= master_height
>> 2;
481 reg_2930
= master_height
;
482 reg_2940
= master_height
;
483 reg_296c
= 0x00000101;
484 if (f
->interlaced_y
) {
490 if (f
->interlaced_uv
)
494 master_height
= (f
->src_h
* 0x00100000) / f
->dst_h
;
495 master_height
= (master_height
>> 1) + (master_height
& 1);
496 reg_2920
= master_height
>> 2;
497 reg_2928
= master_height
>> 2;
498 reg_2930
= master_height
;
499 reg_2940
= master_height
;
502 reg_296c
= 0x00000102;
505 /* FIXME These registers change depending on scaled / unscaled output
506 We really need to work out what they should be */
507 if (f
->src_h
== f
->dst_h
) {
508 reg_2934
= 0x00020000;
509 reg_293c
= 0x00100000;
510 reg_2944
= 0x00040000;
511 reg_294c
= 0x000b0000;
513 reg_2934
= 0x00000FF0;
514 reg_293c
= 0x00000FF0;
515 reg_2944
= 0x00000FF0;
516 reg_294c
= 0x00000FF0;
519 /* The first line to be displayed */
520 reg_2950
= 0x00010000 + src_major_y
;
522 reg_2950
+= 0x00010000;
523 reg_2954
= reg_2950
+ 1;
525 reg_2958
= 0x00010000 + (src_major_y
>> 1);
526 if (f
->interlaced_uv
)
527 reg_2958
+= 0x00010000;
528 reg_295c
= reg_2958
+ 1;
530 if (yi
->decode_height
== 480)
531 reg_289c
= 0x011e0017;
533 reg_289c
= 0x01500017;
536 reg_289c
= (reg_289c
- ((f
->dst_y
& ~1)<<15))-(f
->dst_y
>>1);
538 reg_289c
= (reg_289c
+ ((f
->dst_y
& ~1)<<15))+(f
->dst_y
>>1);
540 /* How much of the source to decode.
541 Take into account the source offset */
542 reg_2960
= ((src_minor_y
+ f
->src_h
+ src_major_y
) - 1) |
543 (((src_minor_uv
+ f
->src_h
+ src_major_uv
- 1) & ~1) << 15);
545 /* Calculate correct value for register 2964 */
546 if (f
->src_h
== f
->dst_h
) {
549 reg_2964
= 2 + ((f
->dst_h
<< 1) / f
->src_h
);
550 reg_2964
= (reg_2964
>> 1) + (reg_2964
& 1);
552 reg_2968
= (reg_2964
<< 16) + reg_2964
+ (reg_2964
>> 1);
553 reg_2964
= (reg_2964
<< 16) + reg_2964
+ (reg_2964
* 46 / 94);
555 /* Okay, we've wasted time working out the correct value,
556 but if we use it, it fouls the the window alignment.
557 Fudge it to what we want... */
558 reg_2964
= 0x00010001 + ((reg_2964
& 0x0000FFFF) - (reg_2964
>> 16));
559 reg_2968
= 0x00010001 + ((reg_2968
& 0x0000FFFF) - (reg_2968
>> 16));
561 /* Deviate further from what it should be. I find the flicker headache
562 inducing so try to reduce it slightly. Leave 2968 as-is otherwise
564 if ((reg_2964
!= 0x00010001) && (f
->dst_h
/ 2 <= f
->src_h
))
565 reg_2964
= (reg_2964
& 0xFFFF0000) + ((reg_2964
& 0x0000FFFF) / 2);
567 if (!f
->interlaced_y
)
568 reg_2964
-= 0x00010001;
569 if (!f
->interlaced_uv
)
570 reg_2968
-= 0x00010001;
572 reg_2964
+= ((reg_2964_base
<< 16) | reg_2964_base
);
573 reg_2968
+= ((reg_2968_base
<< 16) | reg_2968_base
);
575 /* Select the vertical filter */
576 if (f
->src_h
== f
->dst_h
) {
577 /* An exact size match uses filter 0/1 */
581 /* Figure out which filter to use */
582 v_filter_1
= ((f
->src_h
<< 16) / f
->dst_h
) >> 15;
583 v_filter_1
= (v_filter_1
>> 1) + (v_filter_1
& 1);
584 /* Only an exact size match can use filter 0 */
585 v_filter_1
+= !v_filter_1
;
586 v_filter_2
= v_filter_1
;
589 write_reg(reg_2934
, 0x02934);
590 write_reg(reg_293c
, 0x0293c);
591 IVTV_DEBUG_YUV("Update reg 0x2934 %08x->%08x 0x293c %08x->%08x\n",
592 yi
->reg_2934
, reg_2934
, yi
->reg_293c
, reg_293c
);
593 write_reg(reg_2944
, 0x02944);
594 write_reg(reg_294c
, 0x0294c);
595 IVTV_DEBUG_YUV("Update reg 0x2944 %08x->%08x 0x294c %08x->%08x\n",
596 yi
->reg_2944
, reg_2944
, yi
->reg_294c
, reg_294c
);
598 /* Ensure 2970 is 0 (does it ever change ?) */
599 /* write_reg(0,0x02970); */
600 /* IVTV_DEBUG_YUV("Update reg 0x2970 %08x->%08x\n", yi->reg_2970, 0); */
602 write_reg(reg_2930
, 0x02938);
603 write_reg(reg_2930
, 0x02930);
604 IVTV_DEBUG_YUV("Update reg 0x2930 %08x->%08x 0x2938 %08x->%08x\n",
605 yi
->reg_2930
, reg_2930
, yi
->reg_2938
, reg_2930
);
607 write_reg(reg_2928
, 0x02928);
608 write_reg(reg_2928
+ 0x514, 0x0292C);
609 IVTV_DEBUG_YUV("Update reg 0x2928 %08x->%08x 0x292c %08x->%08x\n",
610 yi
->reg_2928
, reg_2928
, yi
->reg_292c
, reg_2928
+ 0x514);
612 write_reg(reg_2920
, 0x02920);
613 write_reg(reg_2920
+ 0x514, 0x02924);
614 IVTV_DEBUG_YUV("Update reg 0x2920 %08x->%08x 0x2924 %08x->%08x\n",
615 yi
->reg_2920
, reg_2920
, yi
->reg_2924
, reg_2920
+ 0x514);
617 write_reg(reg_2918
, 0x02918);
618 write_reg(reg_291c
, 0x0291C);
619 IVTV_DEBUG_YUV("Update reg 0x2918 %08x->%08x 0x291C %08x->%08x\n",
620 yi
->reg_2918
, reg_2918
, yi
->reg_291c
, reg_291c
);
622 write_reg(reg_296c
, 0x0296c);
623 IVTV_DEBUG_YUV("Update reg 0x296c %08x->%08x\n",
624 yi
->reg_296c
, reg_296c
);
626 write_reg(reg_2940
, 0x02948);
627 write_reg(reg_2940
, 0x02940);
628 IVTV_DEBUG_YUV("Update reg 0x2940 %08x->%08x 0x2948 %08x->%08x\n",
629 yi
->reg_2940
, reg_2940
, yi
->reg_2948
, reg_2940
);
631 write_reg(reg_2950
, 0x02950);
632 write_reg(reg_2954
, 0x02954);
633 IVTV_DEBUG_YUV("Update reg 0x2950 %08x->%08x 0x2954 %08x->%08x\n",
634 yi
->reg_2950
, reg_2950
, yi
->reg_2954
, reg_2954
);
636 write_reg(reg_2958
, 0x02958);
637 write_reg(reg_295c
, 0x0295C);
638 IVTV_DEBUG_YUV("Update reg 0x2958 %08x->%08x 0x295C %08x->%08x\n",
639 yi
->reg_2958
, reg_2958
, yi
->reg_295c
, reg_295c
);
641 write_reg(reg_2960
, 0x02960);
642 IVTV_DEBUG_YUV("Update reg 0x2960 %08x->%08x \n",
643 yi
->reg_2960
, reg_2960
);
645 write_reg(reg_2964
, 0x02964);
646 write_reg(reg_2968
, 0x02968);
647 IVTV_DEBUG_YUV("Update reg 0x2964 %08x->%08x 0x2968 %08x->%08x\n",
648 yi
->reg_2964
, reg_2964
, yi
->reg_2968
, reg_2968
);
650 write_reg(reg_289c
, 0x0289c);
651 IVTV_DEBUG_YUV("Update reg 0x289c %08x->%08x\n",
652 yi
->reg_289c
, reg_289c
);
654 /* Only update filter 1 if we really need to */
655 if (v_filter_1
!= yi
->v_filter_1
) {
656 ivtv_yuv_filter(itv
, -1, v_filter_1
, -1);
657 yi
->v_filter_1
= v_filter_1
;
660 /* Only update filter 2 if we really need to */
661 if (v_filter_2
!= yi
->v_filter_2
) {
662 ivtv_yuv_filter(itv
, -1, -1, v_filter_2
);
663 yi
->v_filter_2
= v_filter_2
;
667 /* Modify the supplied coordinate information to fit the visible osd area */
668 static u32
ivtv_yuv_window_setup(struct ivtv
*itv
, struct yuv_frame_info
*f
)
670 struct yuv_frame_info
*of
= &itv
->yuv_info
.old_frame_info
;
675 /* Sorry, but no negative coords for src */
681 /* Can only reduce width down to 1/4 original size */
682 if ((osd_crop
= f
->src_w
- 4 * f
->dst_w
) > 0) {
683 f
->src_x
+= osd_crop
/ 2;
684 f
->src_w
= (f
->src_w
- osd_crop
) & ~3;
685 f
->dst_w
= f
->src_w
/ 4;
686 f
->dst_w
+= f
->dst_w
& 1;
689 /* Can only reduce height down to 1/4 original size */
690 if (f
->src_h
/ f
->dst_h
>= 2) {
691 /* Overflow may be because we're running progressive,
692 so force mode switch */
694 /* Make sure we're still within limits for interlace */
695 if ((osd_crop
= f
->src_h
- 4 * f
->dst_h
) > 0) {
696 /* If we reach here we'll have to force the height. */
697 f
->src_y
+= osd_crop
/ 2;
698 f
->src_h
= (f
->src_h
- osd_crop
) & ~3;
699 f
->dst_h
= f
->src_h
/ 4;
700 f
->dst_h
+= f
->dst_h
& 1;
704 /* If there's nothing to safe to display, we may as well stop now */
705 if ((int)f
->dst_w
<= 2 || (int)f
->dst_h
<= 2 ||
706 (int)f
->src_w
<= 2 || (int)f
->src_h
<= 2) {
707 return IVTV_YUV_UPDATE_INVALID
;
710 /* Ensure video remains inside OSD area */
711 osd_scale
= (f
->src_h
<< 16) / f
->dst_h
;
713 if ((osd_crop
= f
->pan_y
- f
->dst_y
) > 0) {
714 /* Falls off the upper edge - crop */
715 f
->src_y
+= (osd_scale
* osd_crop
) >> 16;
716 f
->src_h
-= (osd_scale
* osd_crop
) >> 16;
717 f
->dst_h
-= osd_crop
;
720 f
->dst_y
-= f
->pan_y
;
723 if ((osd_crop
= f
->dst_h
+ f
->dst_y
- f
->vis_h
) > 0) {
724 /* Falls off the lower edge - crop */
725 f
->dst_h
-= osd_crop
;
726 f
->src_h
-= (osd_scale
* osd_crop
) >> 16;
729 osd_scale
= (f
->src_w
<< 16) / f
->dst_w
;
731 if ((osd_crop
= f
->pan_x
- f
->dst_x
) > 0) {
732 /* Fall off the left edge - crop */
733 f
->src_x
+= (osd_scale
* osd_crop
) >> 16;
734 f
->src_w
-= (osd_scale
* osd_crop
) >> 16;
735 f
->dst_w
-= osd_crop
;
738 f
->dst_x
-= f
->pan_x
;
741 if ((osd_crop
= f
->dst_w
+ f
->dst_x
- f
->vis_w
) > 0) {
742 /* Falls off the right edge - crop */
743 f
->dst_w
-= osd_crop
;
744 f
->src_w
-= (osd_scale
* osd_crop
) >> 16;
747 if (itv
->yuv_info
.track_osd
) {
748 /* The OSD can be moved. Track to it */
749 f
->dst_x
+= itv
->yuv_info
.osd_x_offset
;
750 f
->dst_y
+= itv
->yuv_info
.osd_y_offset
;
753 /* Width & height for both src & dst must be even.
754 Same for coordinates. */
758 f
->src_w
+= f
->src_x
& 1;
767 f
->src_h
+= f
->src_y
& 1;
773 /* Due to rounding, we may have reduced the output size to <1/4 of
774 the source. Check again, but this time just resize. Don't change
775 source coordinates */
776 if (f
->dst_w
< f
->src_w
/ 4) {
778 f
->dst_w
= f
->src_w
/ 4;
779 f
->dst_w
+= f
->dst_w
& 1;
781 if (f
->dst_h
< f
->src_h
/ 4) {
783 f
->dst_h
= f
->src_h
/ 4;
784 f
->dst_h
+= f
->dst_h
& 1;
787 /* Check again. If there's nothing to safe to display, stop now */
788 if ((int)f
->dst_w
<= 2 || (int)f
->dst_h
<= 2 ||
789 (int)f
->src_w
<= 2 || (int)f
->src_h
<= 2) {
790 return IVTV_YUV_UPDATE_INVALID
;
793 /* Both x offset & width are linked, so they have to be done together */
794 if ((of
->dst_w
!= f
->dst_w
) || (of
->src_w
!= f
->src_w
) ||
795 (of
->dst_x
!= f
->dst_x
) || (of
->src_x
!= f
->src_x
) ||
796 (of
->pan_x
!= f
->pan_x
) || (of
->vis_w
!= f
->vis_w
)) {
797 yuv_update
|= IVTV_YUV_UPDATE_HORIZONTAL
;
800 if ((of
->src_h
!= f
->src_h
) || (of
->dst_h
!= f
->dst_h
) ||
801 (of
->dst_y
!= f
->dst_y
) || (of
->src_y
!= f
->src_y
) ||
802 (of
->pan_y
!= f
->pan_y
) || (of
->vis_h
!= f
->vis_h
) ||
803 (of
->lace_mode
!= f
->lace_mode
) ||
804 (of
->interlaced_y
!= f
->interlaced_y
) ||
805 (of
->interlaced_uv
!= f
->interlaced_uv
)) {
806 yuv_update
|= IVTV_YUV_UPDATE_VERTICAL
;
812 /* Update the scaling register to the requested value */
813 void ivtv_yuv_work_handler(struct ivtv
*itv
)
815 struct yuv_playback_info
*yi
= &itv
->yuv_info
;
816 struct yuv_frame_info f
;
817 int frame
= yi
->update_frame
;
820 IVTV_DEBUG_YUV("Update yuv registers for frame %d\n", frame
);
821 f
= yi
->new_frame_info
[frame
];
824 /* Snapshot the osd pan info */
825 f
.pan_x
= yi
->osd_x_pan
;
826 f
.pan_y
= yi
->osd_y_pan
;
827 f
.vis_w
= yi
->osd_vis_w
;
828 f
.vis_h
= yi
->osd_vis_h
;
830 /* Not tracking the osd, so assume full screen */
834 f
.vis_h
= yi
->decode_height
;
837 /* Calculate the display window coordinates. Exit if nothing left */
838 if (!(yuv_update
= ivtv_yuv_window_setup(itv
, &f
)))
841 if (yuv_update
& IVTV_YUV_UPDATE_INVALID
) {
842 write_reg(0x01008080, 0x2898);
843 } else if (yuv_update
) {
844 write_reg(0x00108080, 0x2898);
846 if (yuv_update
& IVTV_YUV_UPDATE_HORIZONTAL
)
847 ivtv_yuv_handle_horizontal(itv
, &f
);
849 if (yuv_update
& IVTV_YUV_UPDATE_VERTICAL
)
850 ivtv_yuv_handle_vertical(itv
, &f
);
852 yi
->old_frame_info
= f
;
855 static void ivtv_yuv_init(struct ivtv
*itv
)
857 struct yuv_playback_info
*yi
= &itv
->yuv_info
;
859 IVTV_DEBUG_YUV("ivtv_yuv_init\n");
861 /* Take a snapshot of the current register settings */
862 yi
->reg_2834
= read_reg(0x02834);
863 yi
->reg_2838
= read_reg(0x02838);
864 yi
->reg_283c
= read_reg(0x0283c);
865 yi
->reg_2840
= read_reg(0x02840);
866 yi
->reg_2844
= read_reg(0x02844);
867 yi
->reg_2848
= read_reg(0x02848);
868 yi
->reg_2854
= read_reg(0x02854);
869 yi
->reg_285c
= read_reg(0x0285c);
870 yi
->reg_2864
= read_reg(0x02864);
871 yi
->reg_2870
= read_reg(0x02870);
872 yi
->reg_2874
= read_reg(0x02874);
873 yi
->reg_2898
= read_reg(0x02898);
874 yi
->reg_2890
= read_reg(0x02890);
876 yi
->reg_289c
= read_reg(0x0289c);
877 yi
->reg_2918
= read_reg(0x02918);
878 yi
->reg_291c
= read_reg(0x0291c);
879 yi
->reg_2920
= read_reg(0x02920);
880 yi
->reg_2924
= read_reg(0x02924);
881 yi
->reg_2928
= read_reg(0x02928);
882 yi
->reg_292c
= read_reg(0x0292c);
883 yi
->reg_2930
= read_reg(0x02930);
884 yi
->reg_2934
= read_reg(0x02934);
885 yi
->reg_2938
= read_reg(0x02938);
886 yi
->reg_293c
= read_reg(0x0293c);
887 yi
->reg_2940
= read_reg(0x02940);
888 yi
->reg_2944
= read_reg(0x02944);
889 yi
->reg_2948
= read_reg(0x02948);
890 yi
->reg_294c
= read_reg(0x0294c);
891 yi
->reg_2950
= read_reg(0x02950);
892 yi
->reg_2954
= read_reg(0x02954);
893 yi
->reg_2958
= read_reg(0x02958);
894 yi
->reg_295c
= read_reg(0x0295c);
895 yi
->reg_2960
= read_reg(0x02960);
896 yi
->reg_2964
= read_reg(0x02964);
897 yi
->reg_2968
= read_reg(0x02968);
898 yi
->reg_296c
= read_reg(0x0296c);
899 yi
->reg_2970
= read_reg(0x02970);
905 /* Set some valid size info */
906 yi
->osd_x_offset
= read_reg(0x02a04) & 0x00000FFF;
907 yi
->osd_y_offset
= (read_reg(0x02a04) >> 16) & 0x00000FFF;
909 /* Bit 2 of reg 2878 indicates current decoder output format
911 if (read_reg(0x2878) & 4)
912 yi
->decode_height
= 576;
914 yi
->decode_height
= 480;
916 if (!itv
->osd_info
) {
917 yi
->osd_vis_w
= 720 - yi
->osd_x_offset
;
918 yi
->osd_vis_h
= yi
->decode_height
- yi
->osd_y_offset
;
920 /* If no visible size set, assume full size */
922 yi
->osd_vis_w
= 720 - yi
->osd_x_offset
;
924 if (!yi
->osd_vis_h
) {
925 yi
->osd_vis_h
= yi
->decode_height
- yi
->osd_y_offset
;
926 } else if (yi
->osd_vis_h
+ yi
->osd_y_offset
> yi
->decode_height
) {
927 /* If output video standard has changed, requested height may
929 IVTV_DEBUG_WARN("Clipping yuv output - fb size (%d) exceeds video standard limit (%d)\n",
930 yi
->osd_vis_h
+ yi
->osd_y_offset
,
932 yi
->osd_vis_h
= yi
->decode_height
- yi
->osd_y_offset
;
936 /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */
937 yi
->blanking_ptr
= kzalloc(720 * 16, GFP_KERNEL
|__GFP_NOWARN
);
938 if (yi
->blanking_ptr
) {
939 yi
->blanking_dmaptr
= pci_map_single(itv
->pdev
, yi
->blanking_ptr
, 720*16, PCI_DMA_TODEVICE
);
941 yi
->blanking_dmaptr
= 0;
942 IVTV_DEBUG_WARN("Failed to allocate yuv blanking buffer\n");
945 /* Enable YUV decoder output */
946 write_reg_sync(0x01, IVTV_REG_VDM
);
948 set_bit(IVTV_F_I_DECODING_YUV
, &itv
->i_flags
);
949 atomic_set(&yi
->next_dma_frame
, 0);
952 /* Get next available yuv buffer on PVR350 */
953 static void ivtv_yuv_next_free(struct ivtv
*itv
)
956 struct yuv_playback_info
*yi
= &itv
->yuv_info
;
958 if (atomic_read(&yi
->next_dma_frame
) == -1)
961 draw
= atomic_read(&yi
->next_fill_frame
);
962 display
= atomic_read(&yi
->next_dma_frame
);
965 display
-= IVTV_YUV_BUFFERS
;
967 if (draw
- display
>= yi
->max_frames_buffered
)
968 draw
= (u8
)(draw
- 1) % IVTV_YUV_BUFFERS
;
970 yi
->new_frame_info
[draw
].update
= 0;
972 yi
->draw_frame
= draw
;
975 /* Set up frame according to ivtv_dma_frame parameters */
976 static void ivtv_yuv_setup_frame(struct ivtv
*itv
, struct ivtv_dma_frame
*args
)
978 struct yuv_playback_info
*yi
= &itv
->yuv_info
;
979 u8 frame
= yi
->draw_frame
;
980 u8 last_frame
= (u8
)(frame
- 1) % IVTV_YUV_BUFFERS
;
981 struct yuv_frame_info
*nf
= &yi
->new_frame_info
[frame
];
982 struct yuv_frame_info
*of
= &yi
->new_frame_info
[last_frame
];
983 int lace_threshold
= yi
->lace_threshold
;
985 /* Preserve old update flag in case we're overwriting a queued frame */
986 int update
= nf
->update
;
988 /* Take a snapshot of the yuv coordinate information */
989 nf
->src_x
= args
->src
.left
;
990 nf
->src_y
= args
->src
.top
;
991 nf
->src_w
= args
->src
.width
;
992 nf
->src_h
= args
->src
.height
;
993 nf
->dst_x
= args
->dst
.left
;
994 nf
->dst_y
= args
->dst
.top
;
995 nf
->dst_w
= args
->dst
.width
;
996 nf
->dst_h
= args
->dst
.height
;
997 nf
->tru_x
= args
->dst
.left
;
998 nf
->tru_w
= args
->src_width
;
999 nf
->tru_h
= args
->src_height
;
1001 /* Are we going to offset the Y plane */
1002 nf
->offset_y
= (nf
->tru_h
+ nf
->src_x
< 512 - 16) ? 1 : 0;
1005 nf
->interlaced_y
= 0;
1006 nf
->interlaced_uv
= 0;
1009 nf
->lace_mode
= yi
->lace_mode
& IVTV_YUV_MODE_MASK
;
1011 if (lace_threshold
< 0)
1012 lace_threshold
= yi
->decode_height
- 1;
1014 /* Work out the lace settings */
1015 switch (nf
->lace_mode
) {
1016 case IVTV_YUV_MODE_PROGRESSIVE
: /* Progressive mode */
1018 if (nf
->tru_h
< 512 || (nf
->tru_h
> 576 && nf
->tru_h
< 1021))
1019 nf
->interlaced_y
= 0;
1021 nf
->interlaced_y
= 1;
1023 if (nf
->tru_h
< 1021 && (nf
->dst_h
>= nf
->src_h
/ 2))
1024 nf
->interlaced_uv
= 0;
1026 nf
->interlaced_uv
= 1;
1029 case IVTV_YUV_MODE_AUTO
:
1030 if (nf
->tru_h
<= lace_threshold
|| nf
->tru_h
> 576 || nf
->tru_w
> 720) {
1032 if ((nf
->tru_h
< 512) ||
1033 (nf
->tru_h
> 576 && nf
->tru_h
< 1021) ||
1034 (nf
->tru_w
> 720 && nf
->tru_h
< 1021))
1035 nf
->interlaced_y
= 0;
1037 nf
->interlaced_y
= 1;
1038 if (nf
->tru_h
< 1021 && (nf
->dst_h
>= nf
->src_h
/ 2))
1039 nf
->interlaced_uv
= 0;
1041 nf
->interlaced_uv
= 1;
1044 nf
->interlaced_y
= 1;
1045 nf
->interlaced_uv
= 1;
1049 case IVTV_YUV_MODE_INTERLACED
: /* Interlace mode */
1052 nf
->interlaced_y
= 1;
1053 nf
->interlaced_uv
= 1;
1057 if (memcmp(&yi
->old_frame_info_args
, nf
, sizeof(*nf
))) {
1058 yi
->old_frame_info_args
= *nf
;
1060 IVTV_DEBUG_YUV("Requesting reg update for frame %d\n", frame
);
1063 nf
->update
|= update
;
1064 nf
->sync_field
= yi
->lace_sync_field
;
1065 nf
->delay
= nf
->sync_field
!= of
->sync_field
;
1068 /* Frame is complete & ready for display */
1069 void ivtv_yuv_frame_complete(struct ivtv
*itv
)
1071 atomic_set(&itv
->yuv_info
.next_fill_frame
,
1072 (itv
->yuv_info
.draw_frame
+ 1) % IVTV_YUV_BUFFERS
);
1075 static int ivtv_yuv_udma_frame(struct ivtv
*itv
, struct ivtv_dma_frame
*args
)
1081 mutex_lock(&itv
->udma
.lock
);
1083 if ((rc
= ivtv_yuv_prep_user_dma(itv
, &itv
->udma
, args
)) != 0) {
1084 mutex_unlock(&itv
->udma
.lock
);
1088 ivtv_udma_prepare(itv
);
1089 prepare_to_wait(&itv
->dma_waitq
, &wait
, TASK_INTERRUPTIBLE
);
1090 /* if no UDMA is pending and no UDMA is in progress, then the DMA
1092 while (test_bit(IVTV_F_I_UDMA_PENDING
, &itv
->i_flags
) ||
1093 test_bit(IVTV_F_I_UDMA
, &itv
->i_flags
)) {
1094 /* don't interrupt if the DMA is in progress but break off
1095 a still pending DMA. */
1096 got_sig
= signal_pending(current
);
1097 if (got_sig
&& test_and_clear_bit(IVTV_F_I_UDMA_PENDING
, &itv
->i_flags
))
1102 finish_wait(&itv
->dma_waitq
, &wait
);
1104 /* Unmap Last DMA Xfer */
1105 ivtv_udma_unmap(itv
);
1108 IVTV_DEBUG_INFO("User stopped YUV UDMA\n");
1109 mutex_unlock(&itv
->udma
.lock
);
1113 ivtv_yuv_frame_complete(itv
);
1115 mutex_unlock(&itv
->udma
.lock
);
1119 /* Setup frame according to V4L2 parameters */
1120 void ivtv_yuv_setup_stream_frame(struct ivtv
*itv
)
1122 struct yuv_playback_info
*yi
= &itv
->yuv_info
;
1123 struct ivtv_dma_frame dma_args
;
1125 ivtv_yuv_next_free(itv
);
1127 /* Copy V4L2 parameters to an ivtv_dma_frame struct... */
1128 dma_args
.y_source
= NULL
;
1129 dma_args
.uv_source
= NULL
;
1130 dma_args
.src
.left
= 0;
1131 dma_args
.src
.top
= 0;
1132 dma_args
.src
.width
= yi
->v4l2_src_w
;
1133 dma_args
.src
.height
= yi
->v4l2_src_h
;
1134 dma_args
.dst
= yi
->main_rect
;
1135 dma_args
.src_width
= yi
->v4l2_src_w
;
1136 dma_args
.src_height
= yi
->v4l2_src_h
;
1138 /* ... and use the same setup routine as ivtv_yuv_prep_frame */
1139 ivtv_yuv_setup_frame(itv
, &dma_args
);
1141 if (!itv
->dma_data_req_offset
)
1142 itv
->dma_data_req_offset
= yuv_offset
[yi
->draw_frame
];
1145 /* Attempt to dma a frame from a user buffer */
1146 int ivtv_yuv_udma_stream_frame(struct ivtv
*itv
, void __user
*src
)
1148 struct yuv_playback_info
*yi
= &itv
->yuv_info
;
1149 struct ivtv_dma_frame dma_args
;
1152 ivtv_yuv_setup_stream_frame(itv
);
1154 /* We only need to supply source addresses for this */
1155 dma_args
.y_source
= src
;
1156 dma_args
.uv_source
= src
+ 720 * ((yi
->v4l2_src_h
+ 31) & ~31);
1157 /* Wait for frame DMA. Note that serialize_lock is locked,
1158 so to allow other processes to access the driver while
1159 we are waiting unlock first and later lock again. */
1160 mutex_unlock(&itv
->serialize_lock
);
1161 res
= ivtv_yuv_udma_frame(itv
, &dma_args
);
1162 mutex_lock(&itv
->serialize_lock
);
1166 /* IVTV_IOC_DMA_FRAME ioctl handler */
1167 int ivtv_yuv_prep_frame(struct ivtv
*itv
, struct ivtv_dma_frame
*args
)
1171 /* IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
1172 ivtv_yuv_next_free(itv
);
1173 ivtv_yuv_setup_frame(itv
, args
);
1174 /* Wait for frame DMA. Note that serialize_lock is locked,
1175 so to allow other processes to access the driver while
1176 we are waiting unlock first and later lock again. */
1177 mutex_unlock(&itv
->serialize_lock
);
1178 res
= ivtv_yuv_udma_frame(itv
, args
);
1179 mutex_lock(&itv
->serialize_lock
);
1183 void ivtv_yuv_close(struct ivtv
*itv
)
1185 struct yuv_playback_info
*yi
= &itv
->yuv_info
;
1186 int h_filter
, v_filter_1
, v_filter_2
;
1188 IVTV_DEBUG_YUV("ivtv_yuv_close\n");
1189 mutex_unlock(&itv
->serialize_lock
);
1190 ivtv_waitq(&itv
->vsync_waitq
);
1191 mutex_lock(&itv
->serialize_lock
);
1194 atomic_set(&yi
->next_dma_frame
, -1);
1195 atomic_set(&yi
->next_fill_frame
, 0);
1197 /* Reset registers we have changed so mpeg playback works */
1199 /* If we fully restore this register, the display may remain active.
1200 Restore, but set one bit to blank the video. Firmware will always
1201 clear this bit when needed, so not a problem. */
1202 write_reg(yi
->reg_2898
| 0x01000000, 0x2898);
1204 write_reg(yi
->reg_2834
, 0x02834);
1205 write_reg(yi
->reg_2838
, 0x02838);
1206 write_reg(yi
->reg_283c
, 0x0283c);
1207 write_reg(yi
->reg_2840
, 0x02840);
1208 write_reg(yi
->reg_2844
, 0x02844);
1209 write_reg(yi
->reg_2848
, 0x02848);
1210 write_reg(yi
->reg_2854
, 0x02854);
1211 write_reg(yi
->reg_285c
, 0x0285c);
1212 write_reg(yi
->reg_2864
, 0x02864);
1213 write_reg(yi
->reg_2870
, 0x02870);
1214 write_reg(yi
->reg_2874
, 0x02874);
1215 write_reg(yi
->reg_2890
, 0x02890);
1216 write_reg(yi
->reg_289c
, 0x0289c);
1218 write_reg(yi
->reg_2918
, 0x02918);
1219 write_reg(yi
->reg_291c
, 0x0291c);
1220 write_reg(yi
->reg_2920
, 0x02920);
1221 write_reg(yi
->reg_2924
, 0x02924);
1222 write_reg(yi
->reg_2928
, 0x02928);
1223 write_reg(yi
->reg_292c
, 0x0292c);
1224 write_reg(yi
->reg_2930
, 0x02930);
1225 write_reg(yi
->reg_2934
, 0x02934);
1226 write_reg(yi
->reg_2938
, 0x02938);
1227 write_reg(yi
->reg_293c
, 0x0293c);
1228 write_reg(yi
->reg_2940
, 0x02940);
1229 write_reg(yi
->reg_2944
, 0x02944);
1230 write_reg(yi
->reg_2948
, 0x02948);
1231 write_reg(yi
->reg_294c
, 0x0294c);
1232 write_reg(yi
->reg_2950
, 0x02950);
1233 write_reg(yi
->reg_2954
, 0x02954);
1234 write_reg(yi
->reg_2958
, 0x02958);
1235 write_reg(yi
->reg_295c
, 0x0295c);
1236 write_reg(yi
->reg_2960
, 0x02960);
1237 write_reg(yi
->reg_2964
, 0x02964);
1238 write_reg(yi
->reg_2968
, 0x02968);
1239 write_reg(yi
->reg_296c
, 0x0296c);
1240 write_reg(yi
->reg_2970
, 0x02970);
1242 /* Prepare to restore filters */
1244 /* First the horizontal filter */
1245 if ((yi
->reg_2834
& 0x0000FFFF) == (yi
->reg_2834
>> 16)) {
1246 /* An exact size match uses filter 0 */
1249 /* Figure out which filter to use */
1250 h_filter
= ((yi
->reg_2834
<< 16) / (yi
->reg_2834
>> 16)) >> 15;
1251 h_filter
= (h_filter
>> 1) + (h_filter
& 1);
1252 /* Only an exact size match can use filter 0. */
1253 h_filter
+= !h_filter
;
1256 /* Now the vertical filter */
1257 if ((yi
->reg_2918
& 0x0000FFFF) == (yi
->reg_2918
>> 16)) {
1258 /* An exact size match uses filter 0/1 */
1262 /* Figure out which filter to use */
1263 v_filter_1
= ((yi
->reg_2918
<< 16) / (yi
->reg_2918
>> 16)) >> 15;
1264 v_filter_1
= (v_filter_1
>> 1) + (v_filter_1
& 1);
1265 /* Only an exact size match can use filter 0 */
1266 v_filter_1
+= !v_filter_1
;
1267 v_filter_2
= v_filter_1
;
1270 /* Now restore the filters */
1271 ivtv_yuv_filter(itv
, h_filter
, v_filter_1
, v_filter_2
);
1273 /* and clear a few registers */
1274 write_reg(0, 0x02814);
1275 write_reg(0, 0x0282c);
1276 write_reg(0, 0x02904);
1277 write_reg(0, 0x02910);
1279 /* Release the blanking buffer */
1280 if (yi
->blanking_ptr
) {
1281 kfree(yi
->blanking_ptr
);
1282 yi
->blanking_ptr
= NULL
;
1283 pci_unmap_single(itv
->pdev
, yi
->blanking_dmaptr
, 720*16, PCI_DMA_TODEVICE
);
1286 /* Invalidate the old dimension information */
1287 yi
->old_frame_info
.src_w
= 0;
1288 yi
->old_frame_info
.src_h
= 0;
1289 yi
->old_frame_info_args
.src_w
= 0;
1290 yi
->old_frame_info_args
.src_h
= 0;
1293 clear_bit(IVTV_F_I_DECODING_YUV
, &itv
->i_flags
);