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 down_read(¤t
->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
= get_user_pages(current
, current
->mm
, uv_dma
.uaddr
, uv_dma
.page_count
, 0, 1, &dma
->map
[y_pages
], NULL
);
81 up_read(¤t
->mm
->mmap_sem
);
83 dma
->page_count
= y_dma
.page_count
+ uv_dma
.page_count
;
85 if (y_pages
+ uv_pages
!= dma
->page_count
) {
87 ("failed to map user pages, returned %d instead of %d\n",
88 y_pages
+ uv_pages
, dma
->page_count
);
90 for (i
= 0; i
< dma
->page_count
; i
++) {
91 put_page(dma
->map
[i
]);
97 /* Fill & map SG List */
98 if (ivtv_udma_fill_sg_list (dma
, &uv_dma
, ivtv_udma_fill_sg_list (dma
, &y_dma
, 0)) < 0) {
99 IVTV_DEBUG_WARN("could not allocate bounce buffers for highmem userspace buffers\n");
100 for (i
= 0; i
< dma
->page_count
; i
++) {
101 put_page(dma
->map
[i
]);
106 dma
->SG_length
= pci_map_sg(itv
->dev
, dma
->SGlist
, dma
->page_count
, PCI_DMA_TODEVICE
);
108 /* Fill SG Array with new values */
109 ivtv_udma_fill_sg_array(dma
, y_buffer_offset
, uv_buffer_offset
, y_size
);
111 /* If we've offset the y plane, ensure top area is blanked */
112 if (f
->offset_y
&& yi
->blanking_dmaptr
) {
113 dma
->SGarray
[dma
->SG_length
].size
= cpu_to_le32(720*16);
114 dma
->SGarray
[dma
->SG_length
].src
= cpu_to_le32(yi
->blanking_dmaptr
);
115 dma
->SGarray
[dma
->SG_length
].dst
= cpu_to_le32(IVTV_DECODER_OFFSET
+ yuv_offset
[frame
]);
119 /* Tag SG Array with Interrupt Bit */
120 dma
->SGarray
[dma
->SG_length
- 1].size
|= cpu_to_le32(0x80000000);
122 ivtv_udma_sync_for_device(itv
);
126 /* We rely on a table held in the firmware - Quick check. */
127 int ivtv_yuv_filter_check(struct ivtv
*itv
)
131 for (i
= 0, y
= 16, uv
= 4; i
< 16; i
++, y
+= 24, uv
+= 12) {
132 if ((read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET
+ y
) != i
<< 16) ||
133 (read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET
+ uv
) != i
<< 16)) {
134 IVTV_WARN ("YUV filter table not found in firmware.\n");
141 static void ivtv_yuv_filter(struct ivtv
*itv
, int h_filter
, int v_filter_1
, int v_filter_2
)
145 /* If any filter is -1, then don't update it */
149 i
= IVTV_YUV_HORIZONTAL_FILTER_OFFSET
+ (h_filter
* 384);
150 for (line
= 0; line
< 16; line
++) {
151 write_reg(read_dec(i
), 0x02804);
152 write_reg(read_dec(i
), 0x0281c);
154 write_reg(read_dec(i
), 0x02808);
155 write_reg(read_dec(i
), 0x02820);
157 write_reg(read_dec(i
), 0x0280c);
158 write_reg(read_dec(i
), 0x02824);
160 write_reg(read_dec(i
), 0x02810);
161 write_reg(read_dec(i
), 0x02828);
163 write_reg(read_dec(i
), 0x02814);
164 write_reg(read_dec(i
), 0x0282c);
166 write_reg(0, 0x02818);
167 write_reg(0, 0x02830);
169 IVTV_DEBUG_YUV("h_filter -> %d\n", h_filter
);
172 if (v_filter_1
> -1) {
175 i
= IVTV_YUV_VERTICAL_FILTER_OFFSET
+ (v_filter_1
* 192);
176 for (line
= 0; line
< 16; line
++) {
177 write_reg(read_dec(i
), 0x02900);
179 write_reg(read_dec(i
), 0x02904);
181 write_reg(0, 0x02908);
183 IVTV_DEBUG_YUV("v_filter_1 -> %d\n", v_filter_1
);
186 if (v_filter_2
> -1) {
189 i
= IVTV_YUV_VERTICAL_FILTER_OFFSET
+ (v_filter_2
* 192);
190 for (line
= 0; line
< 16; line
++) {
191 write_reg(read_dec(i
), 0x0290c);
193 write_reg(read_dec(i
), 0x02910);
195 write_reg(0, 0x02914);
197 IVTV_DEBUG_YUV("v_filter_2 -> %d\n", v_filter_2
);
201 static void ivtv_yuv_handle_horizontal(struct ivtv
*itv
, struct yuv_frame_info
*f
)
203 struct yuv_playback_info
*yi
= &itv
->yuv_info
;
204 u32 reg_2834
, reg_2838
, reg_283c
;
205 u32 reg_2844
, reg_2854
, reg_285c
;
206 u32 reg_2864
, reg_2874
, reg_2890
;
207 u32 reg_2870
, reg_2870_base
, reg_2870_offset
;
213 ("Adjust to width %d src_w %d dst_w %d src_x %d dst_x %d\n",
214 f
->tru_w
, f
->src_w
, f
->dst_w
, f
->src_x
, f
->dst_x
);
216 /* How wide is the src image */
217 x_cutoff
= f
->src_w
+ f
->src_x
;
219 /* Set the display width */
223 /* Set the display position */
226 /* Index into the image horizontally */
229 /* 2870 is normally fudged to align video coords with osd coords.
230 If running full screen, it causes an unwanted left shift
231 Remove the fudge if we almost fill the screen.
232 Gradually adjust the offset to avoid the video 'snapping'
233 left/right if it gets dragged through this region.
234 Only do this if osd is full width. */
235 if (f
->vis_w
== 720) {
236 if ((f
->tru_x
- f
->pan_x
> -1) && (f
->tru_x
- f
->pan_x
<= 40) && (f
->dst_w
>= 680))
237 reg_2870
= 10 - (f
->tru_x
- f
->pan_x
) / 4;
238 else if ((f
->tru_x
- f
->pan_x
< 0) && (f
->tru_x
- f
->pan_x
>= -20) && (f
->dst_w
>= 660))
239 reg_2870
= (10 + (f
->tru_x
- f
->pan_x
) / 2);
241 if (f
->dst_w
>= f
->src_w
)
242 reg_2870
= reg_2870
<< 16 | reg_2870
;
244 reg_2870
= ((reg_2870
& ~1) << 15) | (reg_2870
& ~1);
247 if (f
->dst_w
< f
->src_w
)
248 reg_2870
= 0x000d000e - reg_2870
;
250 reg_2870
= 0x0012000e - reg_2870
;
252 /* We're also using 2870 to shift the image left (src_x & negative dst_x) */
253 reg_2870_offset
= (f
->src_x
* ((f
->dst_w
<< 21) / f
->src_w
)) >> 19;
255 if (f
->dst_w
>= f
->src_w
) {
257 master_width
= (f
->src_w
* 0x00200000) / (f
->dst_w
);
258 if (master_width
* f
->dst_w
!= f
->src_w
* 0x00200000)
260 reg_2834
= (reg_2834
<< 16) | x_cutoff
;
261 reg_2838
= (reg_2838
<< 16) | x_cutoff
;
262 reg_283c
= master_width
>> 2;
263 reg_2844
= master_width
>> 2;
264 reg_2854
= master_width
;
265 reg_285c
= master_width
>> 1;
266 reg_2864
= master_width
>> 1;
268 /* We also need to factor in the scaling
269 (src_w - dst_w) / (src_w / 4) */
270 if (f
->dst_w
> f
->src_w
)
271 reg_2870_base
= ((f
->dst_w
- f
->src_w
)<<16) / (f
->src_w
<<14);
275 reg_2870
+= (((reg_2870_offset
<< 14) & 0xFFFF0000) | reg_2870_offset
>> 2) + (reg_2870_base
<< 17 | reg_2870_base
);
277 } else if (f
->dst_w
< f
->src_w
/ 2) {
278 master_width
= (f
->src_w
* 0x00080000) / f
->dst_w
;
279 if (master_width
* f
->dst_w
!= f
->src_w
* 0x00080000)
281 reg_2834
= (reg_2834
<< 16) | x_cutoff
;
282 reg_2838
= (reg_2838
<< 16) | x_cutoff
;
283 reg_283c
= master_width
>> 2;
284 reg_2844
= master_width
>> 1;
285 reg_2854
= master_width
;
286 reg_285c
= master_width
>> 1;
287 reg_2864
= master_width
>> 1;
288 reg_2870
+= ((reg_2870_offset
<< 15) & 0xFFFF0000) | reg_2870_offset
;
289 reg_2870
+= (5 - (((f
->src_w
+ f
->src_w
/ 2) - 1) / f
->dst_w
)) << 16;
290 reg_2874
= 0x00000012;
292 master_width
= (f
->src_w
* 0x00100000) / f
->dst_w
;
293 if (master_width
* f
->dst_w
!= f
->src_w
* 0x00100000)
295 reg_2834
= (reg_2834
<< 16) | x_cutoff
;
296 reg_2838
= (reg_2838
<< 16) | x_cutoff
;
297 reg_283c
= master_width
>> 2;
298 reg_2844
= master_width
>> 1;
299 reg_2854
= master_width
;
300 reg_285c
= master_width
>> 1;
301 reg_2864
= master_width
>> 1;
302 reg_2870
+= ((reg_2870_offset
<< 14) & 0xFFFF0000) | reg_2870_offset
>> 1;
303 reg_2870
+= (5 - (((f
->src_w
* 3) - 1) / f
->dst_w
)) << 16;
304 reg_2874
= 0x00000001;
307 /* Select the horizontal filter */
308 if (f
->src_w
== f
->dst_w
) {
309 /* An exact size match uses filter 0 */
312 /* Figure out which filter to use */
313 h_filter
= ((f
->src_w
<< 16) / f
->dst_w
) >> 15;
314 h_filter
= (h_filter
>> 1) + (h_filter
& 1);
315 /* Only an exact size match can use filter 0 */
316 h_filter
+= !h_filter
;
319 write_reg(reg_2834
, 0x02834);
320 write_reg(reg_2838
, 0x02838);
321 IVTV_DEBUG_YUV("Update reg 0x2834 %08x->%08x 0x2838 %08x->%08x\n",
322 yi
->reg_2834
, reg_2834
, yi
->reg_2838
, reg_2838
);
324 write_reg(reg_283c
, 0x0283c);
325 write_reg(reg_2844
, 0x02844);
327 IVTV_DEBUG_YUV("Update reg 0x283c %08x->%08x 0x2844 %08x->%08x\n",
328 yi
->reg_283c
, reg_283c
, yi
->reg_2844
, reg_2844
);
330 write_reg(0x00080514, 0x02840);
331 write_reg(0x00100514, 0x02848);
332 IVTV_DEBUG_YUV("Update reg 0x2840 %08x->%08x 0x2848 %08x->%08x\n",
333 yi
->reg_2840
, 0x00080514, yi
->reg_2848
, 0x00100514);
335 write_reg(reg_2854
, 0x02854);
336 IVTV_DEBUG_YUV("Update reg 0x2854 %08x->%08x \n",
337 yi
->reg_2854
, reg_2854
);
339 write_reg(reg_285c
, 0x0285c);
340 write_reg(reg_2864
, 0x02864);
341 IVTV_DEBUG_YUV("Update reg 0x285c %08x->%08x 0x2864 %08x->%08x\n",
342 yi
->reg_285c
, reg_285c
, yi
->reg_2864
, reg_2864
);
344 write_reg(reg_2874
, 0x02874);
345 IVTV_DEBUG_YUV("Update reg 0x2874 %08x->%08x\n",
346 yi
->reg_2874
, reg_2874
);
348 write_reg(reg_2870
, 0x02870);
349 IVTV_DEBUG_YUV("Update reg 0x2870 %08x->%08x\n",
350 yi
->reg_2870
, reg_2870
);
352 write_reg(reg_2890
, 0x02890);
353 IVTV_DEBUG_YUV("Update reg 0x2890 %08x->%08x\n",
354 yi
->reg_2890
, reg_2890
);
356 /* Only update the filter if we really need to */
357 if (h_filter
!= yi
->h_filter
) {
358 ivtv_yuv_filter(itv
, h_filter
, -1, -1);
359 yi
->h_filter
= h_filter
;
363 static void ivtv_yuv_handle_vertical(struct ivtv
*itv
, struct yuv_frame_info
*f
)
365 struct yuv_playback_info
*yi
= &itv
->yuv_info
;
367 u32 reg_2918
, reg_291c
, reg_2920
, reg_2928
;
368 u32 reg_2930
, reg_2934
, reg_293c
;
369 u32 reg_2940
, reg_2944
, reg_294c
;
370 u32 reg_2950
, reg_2954
, reg_2958
, reg_295c
;
371 u32 reg_2960
, reg_2964
, reg_2968
, reg_296c
;
373 u32 src_major_y
, src_minor_y
;
374 u32 src_major_uv
, src_minor_uv
;
375 u32 reg_2964_base
, reg_2968_base
;
376 int v_filter_1
, v_filter_2
;
379 ("Adjust to height %d src_h %d dst_h %d src_y %d dst_y %d\n",
380 f
->tru_h
, f
->src_h
, f
->dst_h
, f
->src_y
, f
->dst_y
);
382 /* What scaling mode is being used... */
383 IVTV_DEBUG_YUV("Scaling mode Y: %s\n",
384 f
->interlaced_y
? "Interlaced" : "Progressive");
386 IVTV_DEBUG_YUV("Scaling mode UV: %s\n",
387 f
->interlaced_uv
? "Interlaced" : "Progressive");
389 /* What is the source video being treated as... */
390 IVTV_DEBUG_WARN("Source video: %s\n",
391 f
->interlaced
? "Interlaced" : "Progressive");
393 /* We offset into the image using two different index methods, so split
394 the y source coord into two parts. */
396 src_minor_uv
= f
->src_y
;
400 src_major_uv
= f
->src_y
- 8;
403 src_minor_y
= src_minor_uv
;
404 src_major_y
= src_major_uv
;
410 reg_2918
= (f
->dst_h
<< 16) | (f
->src_h
+ src_minor_y
);
412 reg_2918
= (f
->dst_h
<< 16) | ((f
->src_h
+ src_minor_y
) << 1);
414 if (f
->interlaced_uv
)
415 reg_291c
= (f
->dst_h
<< 16) | ((f
->src_h
+ src_minor_uv
) >> 1);
417 reg_291c
= (f
->dst_h
<< 16) | (f
->src_h
+ src_minor_uv
);
419 reg_2964_base
= (src_minor_y
* ((f
->dst_h
<< 16) / f
->src_h
)) >> 14;
420 reg_2968_base
= (src_minor_uv
* ((f
->dst_h
<< 16) / f
->src_h
)) >> 14;
422 if (f
->dst_h
/ 2 >= f
->src_h
&& !f
->interlaced_y
) {
423 master_height
= (f
->src_h
* 0x00400000) / f
->dst_h
;
424 if ((f
->src_h
* 0x00400000) - (master_height
* f
->dst_h
) >= f
->dst_h
/ 2)
426 reg_2920
= master_height
>> 2;
427 reg_2928
= master_height
>> 3;
428 reg_2930
= master_height
;
429 reg_2940
= master_height
>> 1;
432 reg_296c
= 0x00000000;
433 } else if (f
->dst_h
>= f
->src_h
) {
434 master_height
= (f
->src_h
* 0x00400000) / f
->dst_h
;
435 master_height
= (master_height
>> 1) + (master_height
& 1);
436 reg_2920
= master_height
>> 2;
437 reg_2928
= master_height
>> 2;
438 reg_2930
= master_height
;
439 reg_2940
= master_height
>> 1;
440 reg_296c
= 0x00000000;
441 if (f
->interlaced_y
) {
447 if (f
->interlaced_uv
)
450 } else if (f
->dst_h
>= f
->src_h
/ 2) {
451 master_height
= (f
->src_h
* 0x00200000) / f
->dst_h
;
452 master_height
= (master_height
>> 1) + (master_height
& 1);
453 reg_2920
= master_height
>> 2;
454 reg_2928
= master_height
>> 2;
455 reg_2930
= master_height
;
456 reg_2940
= master_height
;
457 reg_296c
= 0x00000101;
458 if (f
->interlaced_y
) {
464 if (f
->interlaced_uv
)
468 master_height
= (f
->src_h
* 0x00100000) / f
->dst_h
;
469 master_height
= (master_height
>> 1) + (master_height
& 1);
470 reg_2920
= master_height
>> 2;
471 reg_2928
= master_height
>> 2;
472 reg_2930
= master_height
;
473 reg_2940
= master_height
;
476 reg_296c
= 0x00000102;
479 /* FIXME These registers change depending on scaled / unscaled output
480 We really need to work out what they should be */
481 if (f
->src_h
== f
->dst_h
) {
482 reg_2934
= 0x00020000;
483 reg_293c
= 0x00100000;
484 reg_2944
= 0x00040000;
485 reg_294c
= 0x000b0000;
487 reg_2934
= 0x00000FF0;
488 reg_293c
= 0x00000FF0;
489 reg_2944
= 0x00000FF0;
490 reg_294c
= 0x00000FF0;
493 /* The first line to be displayed */
494 reg_2950
= 0x00010000 + src_major_y
;
496 reg_2950
+= 0x00010000;
497 reg_2954
= reg_2950
+ 1;
499 reg_2958
= 0x00010000 + (src_major_y
>> 1);
500 if (f
->interlaced_uv
)
501 reg_2958
+= 0x00010000;
502 reg_295c
= reg_2958
+ 1;
504 if (yi
->decode_height
== 480)
505 reg_289c
= 0x011e0017;
507 reg_289c
= 0x01500017;
510 reg_289c
= (reg_289c
- ((f
->dst_y
& ~1)<<15))-(f
->dst_y
>>1);
512 reg_289c
= (reg_289c
+ ((f
->dst_y
& ~1)<<15))+(f
->dst_y
>>1);
514 /* How much of the source to decode.
515 Take into account the source offset */
516 reg_2960
= ((src_minor_y
+ f
->src_h
+ src_major_y
) - 1) |
517 (((src_minor_uv
+ f
->src_h
+ src_major_uv
- 1) & ~1) << 15);
519 /* Calculate correct value for register 2964 */
520 if (f
->src_h
== f
->dst_h
) {
523 reg_2964
= 2 + ((f
->dst_h
<< 1) / f
->src_h
);
524 reg_2964
= (reg_2964
>> 1) + (reg_2964
& 1);
526 reg_2968
= (reg_2964
<< 16) + reg_2964
+ (reg_2964
>> 1);
527 reg_2964
= (reg_2964
<< 16) + reg_2964
+ (reg_2964
* 46 / 94);
529 /* Okay, we've wasted time working out the correct value,
530 but if we use it, it fouls the the window alignment.
531 Fudge it to what we want... */
532 reg_2964
= 0x00010001 + ((reg_2964
& 0x0000FFFF) - (reg_2964
>> 16));
533 reg_2968
= 0x00010001 + ((reg_2968
& 0x0000FFFF) - (reg_2968
>> 16));
535 /* Deviate further from what it should be. I find the flicker headache
536 inducing so try to reduce it slightly. Leave 2968 as-is otherwise
538 if ((reg_2964
!= 0x00010001) && (f
->dst_h
/ 2 <= f
->src_h
))
539 reg_2964
= (reg_2964
& 0xFFFF0000) + ((reg_2964
& 0x0000FFFF) / 2);
541 if (!f
->interlaced_y
)
542 reg_2964
-= 0x00010001;
543 if (!f
->interlaced_uv
)
544 reg_2968
-= 0x00010001;
546 reg_2964
+= ((reg_2964_base
<< 16) | reg_2964_base
);
547 reg_2968
+= ((reg_2968_base
<< 16) | reg_2968_base
);
549 /* Select the vertical filter */
550 if (f
->src_h
== f
->dst_h
) {
551 /* An exact size match uses filter 0/1 */
555 /* Figure out which filter to use */
556 v_filter_1
= ((f
->src_h
<< 16) / f
->dst_h
) >> 15;
557 v_filter_1
= (v_filter_1
>> 1) + (v_filter_1
& 1);
558 /* Only an exact size match can use filter 0 */
559 v_filter_1
+= !v_filter_1
;
560 v_filter_2
= v_filter_1
;
563 write_reg(reg_2934
, 0x02934);
564 write_reg(reg_293c
, 0x0293c);
565 IVTV_DEBUG_YUV("Update reg 0x2934 %08x->%08x 0x293c %08x->%08x\n",
566 yi
->reg_2934
, reg_2934
, yi
->reg_293c
, reg_293c
);
567 write_reg(reg_2944
, 0x02944);
568 write_reg(reg_294c
, 0x0294c);
569 IVTV_DEBUG_YUV("Update reg 0x2944 %08x->%08x 0x294c %08x->%08x\n",
570 yi
->reg_2944
, reg_2944
, yi
->reg_294c
, reg_294c
);
572 /* Ensure 2970 is 0 (does it ever change ?) */
573 /* write_reg(0,0x02970); */
574 /* IVTV_DEBUG_YUV("Update reg 0x2970 %08x->%08x\n", yi->reg_2970, 0); */
576 write_reg(reg_2930
, 0x02938);
577 write_reg(reg_2930
, 0x02930);
578 IVTV_DEBUG_YUV("Update reg 0x2930 %08x->%08x 0x2938 %08x->%08x\n",
579 yi
->reg_2930
, reg_2930
, yi
->reg_2938
, reg_2930
);
581 write_reg(reg_2928
, 0x02928);
582 write_reg(reg_2928
+ 0x514, 0x0292C);
583 IVTV_DEBUG_YUV("Update reg 0x2928 %08x->%08x 0x292c %08x->%08x\n",
584 yi
->reg_2928
, reg_2928
, yi
->reg_292c
, reg_2928
+ 0x514);
586 write_reg(reg_2920
, 0x02920);
587 write_reg(reg_2920
+ 0x514, 0x02924);
588 IVTV_DEBUG_YUV("Update reg 0x2920 %08x->%08x 0x2924 %08x->%08x\n",
589 yi
->reg_2920
, reg_2920
, yi
->reg_2924
, reg_2920
+ 0x514);
591 write_reg(reg_2918
, 0x02918);
592 write_reg(reg_291c
, 0x0291C);
593 IVTV_DEBUG_YUV("Update reg 0x2918 %08x->%08x 0x291C %08x->%08x\n",
594 yi
->reg_2918
, reg_2918
, yi
->reg_291c
, reg_291c
);
596 write_reg(reg_296c
, 0x0296c);
597 IVTV_DEBUG_YUV("Update reg 0x296c %08x->%08x\n",
598 yi
->reg_296c
, reg_296c
);
600 write_reg(reg_2940
, 0x02948);
601 write_reg(reg_2940
, 0x02940);
602 IVTV_DEBUG_YUV("Update reg 0x2940 %08x->%08x 0x2948 %08x->%08x\n",
603 yi
->reg_2940
, reg_2940
, yi
->reg_2948
, reg_2940
);
605 write_reg(reg_2950
, 0x02950);
606 write_reg(reg_2954
, 0x02954);
607 IVTV_DEBUG_YUV("Update reg 0x2950 %08x->%08x 0x2954 %08x->%08x\n",
608 yi
->reg_2950
, reg_2950
, yi
->reg_2954
, reg_2954
);
610 write_reg(reg_2958
, 0x02958);
611 write_reg(reg_295c
, 0x0295C);
612 IVTV_DEBUG_YUV("Update reg 0x2958 %08x->%08x 0x295C %08x->%08x\n",
613 yi
->reg_2958
, reg_2958
, yi
->reg_295c
, reg_295c
);
615 write_reg(reg_2960
, 0x02960);
616 IVTV_DEBUG_YUV("Update reg 0x2960 %08x->%08x \n",
617 yi
->reg_2960
, reg_2960
);
619 write_reg(reg_2964
, 0x02964);
620 write_reg(reg_2968
, 0x02968);
621 IVTV_DEBUG_YUV("Update reg 0x2964 %08x->%08x 0x2968 %08x->%08x\n",
622 yi
->reg_2964
, reg_2964
, yi
->reg_2968
, reg_2968
);
624 write_reg(reg_289c
, 0x0289c);
625 IVTV_DEBUG_YUV("Update reg 0x289c %08x->%08x\n",
626 yi
->reg_289c
, reg_289c
);
628 /* Only update filter 1 if we really need to */
629 if (v_filter_1
!= yi
->v_filter_1
) {
630 ivtv_yuv_filter(itv
, -1, v_filter_1
, -1);
631 yi
->v_filter_1
= v_filter_1
;
634 /* Only update filter 2 if we really need to */
635 if (v_filter_2
!= yi
->v_filter_2
) {
636 ivtv_yuv_filter(itv
, -1, -1, v_filter_2
);
637 yi
->v_filter_2
= v_filter_2
;
641 /* Modify the supplied coordinate information to fit the visible osd area */
642 static u32
ivtv_yuv_window_setup(struct ivtv
*itv
, struct yuv_frame_info
*f
)
644 struct yuv_frame_info
*of
= &itv
->yuv_info
.old_frame_info
;
649 /* Sorry, but no negative coords for src */
655 /* Can only reduce width down to 1/4 original size */
656 if ((osd_crop
= f
->src_w
- 4 * f
->dst_w
) > 0) {
657 f
->src_x
+= osd_crop
/ 2;
658 f
->src_w
= (f
->src_w
- osd_crop
) & ~3;
659 f
->dst_w
= f
->src_w
/ 4;
660 f
->dst_w
+= f
->dst_w
& 1;
663 /* Can only reduce height down to 1/4 original size */
664 if (f
->src_h
/ f
->dst_h
>= 2) {
665 /* Overflow may be because we're running progressive,
666 so force mode switch */
668 /* Make sure we're still within limits for interlace */
669 if ((osd_crop
= f
->src_h
- 4 * f
->dst_h
) > 0) {
670 /* If we reach here we'll have to force the height. */
671 f
->src_y
+= osd_crop
/ 2;
672 f
->src_h
= (f
->src_h
- osd_crop
) & ~3;
673 f
->dst_h
= f
->src_h
/ 4;
674 f
->dst_h
+= f
->dst_h
& 1;
678 /* If there's nothing to safe to display, we may as well stop now */
679 if ((int)f
->dst_w
<= 2 || (int)f
->dst_h
<= 2 ||
680 (int)f
->src_w
<= 2 || (int)f
->src_h
<= 2) {
681 return IVTV_YUV_UPDATE_INVALID
;
684 /* Ensure video remains inside OSD area */
685 osd_scale
= (f
->src_h
<< 16) / f
->dst_h
;
687 if ((osd_crop
= f
->pan_y
- f
->dst_y
) > 0) {
688 /* Falls off the upper edge - crop */
689 f
->src_y
+= (osd_scale
* osd_crop
) >> 16;
690 f
->src_h
-= (osd_scale
* osd_crop
) >> 16;
691 f
->dst_h
-= osd_crop
;
694 f
->dst_y
-= f
->pan_y
;
697 if ((osd_crop
= f
->dst_h
+ f
->dst_y
- f
->vis_h
) > 0) {
698 /* Falls off the lower edge - crop */
699 f
->dst_h
-= osd_crop
;
700 f
->src_h
-= (osd_scale
* osd_crop
) >> 16;
703 osd_scale
= (f
->src_w
<< 16) / f
->dst_w
;
705 if ((osd_crop
= f
->pan_x
- f
->dst_x
) > 0) {
706 /* Fall off the left edge - crop */
707 f
->src_x
+= (osd_scale
* osd_crop
) >> 16;
708 f
->src_w
-= (osd_scale
* osd_crop
) >> 16;
709 f
->dst_w
-= osd_crop
;
712 f
->dst_x
-= f
->pan_x
;
715 if ((osd_crop
= f
->dst_w
+ f
->dst_x
- f
->vis_w
) > 0) {
716 /* Falls off the right edge - crop */
717 f
->dst_w
-= osd_crop
;
718 f
->src_w
-= (osd_scale
* osd_crop
) >> 16;
721 /* The OSD can be moved. Track to it */
722 f
->dst_x
+= itv
->yuv_info
.osd_x_offset
;
723 f
->dst_y
+= itv
->yuv_info
.osd_y_offset
;
725 /* Width & height for both src & dst must be even.
726 Same for coordinates. */
730 f
->src_w
+= f
->src_x
& 1;
739 f
->src_h
+= f
->src_y
& 1;
745 /* Due to rounding, we may have reduced the output size to <1/4 of
746 the source. Check again, but this time just resize. Don't change
747 source coordinates */
748 if (f
->dst_w
< f
->src_w
/ 4) {
750 f
->dst_w
= f
->src_w
/ 4;
751 f
->dst_w
+= f
->dst_w
& 1;
753 if (f
->dst_h
< f
->src_h
/ 4) {
755 f
->dst_h
= f
->src_h
/ 4;
756 f
->dst_h
+= f
->dst_h
& 1;
759 /* Check again. If there's nothing to safe to display, stop now */
760 if ((int)f
->dst_w
<= 2 || (int)f
->dst_h
<= 2 ||
761 (int)f
->src_w
<= 2 || (int)f
->src_h
<= 2) {
762 return IVTV_YUV_UPDATE_INVALID
;
765 /* Both x offset & width are linked, so they have to be done together */
766 if ((of
->dst_w
!= f
->dst_w
) || (of
->src_w
!= f
->src_w
) ||
767 (of
->dst_x
!= f
->dst_x
) || (of
->src_x
!= f
->src_x
) ||
768 (of
->pan_x
!= f
->pan_x
) || (of
->vis_w
!= f
->vis_w
)) {
769 yuv_update
|= IVTV_YUV_UPDATE_HORIZONTAL
;
772 if ((of
->src_h
!= f
->src_h
) || (of
->dst_h
!= f
->dst_h
) ||
773 (of
->dst_y
!= f
->dst_y
) || (of
->src_y
!= f
->src_y
) ||
774 (of
->pan_y
!= f
->pan_y
) || (of
->vis_h
!= f
->vis_h
) ||
775 (of
->lace_mode
!= f
->lace_mode
) ||
776 (of
->interlaced_y
!= f
->interlaced_y
) ||
777 (of
->interlaced_uv
!= f
->interlaced_uv
)) {
778 yuv_update
|= IVTV_YUV_UPDATE_VERTICAL
;
784 /* Update the scaling register to the requested value */
785 void ivtv_yuv_work_handler(struct ivtv
*itv
)
787 struct yuv_playback_info
*yi
= &itv
->yuv_info
;
788 struct yuv_frame_info f
;
789 int frame
= yi
->update_frame
;
792 IVTV_DEBUG_YUV("Update yuv registers for frame %d\n", frame
);
793 f
= yi
->new_frame_info
[frame
];
795 /* Update the osd pan info */
796 f
.pan_x
= yi
->osd_x_pan
;
797 f
.pan_y
= yi
->osd_y_pan
;
798 f
.vis_w
= yi
->osd_vis_w
;
799 f
.vis_h
= yi
->osd_vis_h
;
801 /* Calculate the display window coordinates. Exit if nothing left */
802 if (!(yuv_update
= ivtv_yuv_window_setup(itv
, &f
)))
805 if (yuv_update
& IVTV_YUV_UPDATE_INVALID
) {
806 write_reg(0x01008080, 0x2898);
807 } else if (yuv_update
) {
808 write_reg(0x00108080, 0x2898);
810 if (yuv_update
& IVTV_YUV_UPDATE_HORIZONTAL
)
811 ivtv_yuv_handle_horizontal(itv
, &f
);
813 if (yuv_update
& IVTV_YUV_UPDATE_VERTICAL
)
814 ivtv_yuv_handle_vertical(itv
, &f
);
816 yi
->old_frame_info
= f
;
819 static void ivtv_yuv_init(struct ivtv
*itv
)
821 struct yuv_playback_info
*yi
= &itv
->yuv_info
;
823 IVTV_DEBUG_YUV("ivtv_yuv_init\n");
825 /* Take a snapshot of the current register settings */
826 yi
->reg_2834
= read_reg(0x02834);
827 yi
->reg_2838
= read_reg(0x02838);
828 yi
->reg_283c
= read_reg(0x0283c);
829 yi
->reg_2840
= read_reg(0x02840);
830 yi
->reg_2844
= read_reg(0x02844);
831 yi
->reg_2848
= read_reg(0x02848);
832 yi
->reg_2854
= read_reg(0x02854);
833 yi
->reg_285c
= read_reg(0x0285c);
834 yi
->reg_2864
= read_reg(0x02864);
835 yi
->reg_2870
= read_reg(0x02870);
836 yi
->reg_2874
= read_reg(0x02874);
837 yi
->reg_2898
= read_reg(0x02898);
838 yi
->reg_2890
= read_reg(0x02890);
840 yi
->reg_289c
= read_reg(0x0289c);
841 yi
->reg_2918
= read_reg(0x02918);
842 yi
->reg_291c
= read_reg(0x0291c);
843 yi
->reg_2920
= read_reg(0x02920);
844 yi
->reg_2924
= read_reg(0x02924);
845 yi
->reg_2928
= read_reg(0x02928);
846 yi
->reg_292c
= read_reg(0x0292c);
847 yi
->reg_2930
= read_reg(0x02930);
848 yi
->reg_2934
= read_reg(0x02934);
849 yi
->reg_2938
= read_reg(0x02938);
850 yi
->reg_293c
= read_reg(0x0293c);
851 yi
->reg_2940
= read_reg(0x02940);
852 yi
->reg_2944
= read_reg(0x02944);
853 yi
->reg_2948
= read_reg(0x02948);
854 yi
->reg_294c
= read_reg(0x0294c);
855 yi
->reg_2950
= read_reg(0x02950);
856 yi
->reg_2954
= read_reg(0x02954);
857 yi
->reg_2958
= read_reg(0x02958);
858 yi
->reg_295c
= read_reg(0x0295c);
859 yi
->reg_2960
= read_reg(0x02960);
860 yi
->reg_2964
= read_reg(0x02964);
861 yi
->reg_2968
= read_reg(0x02968);
862 yi
->reg_296c
= read_reg(0x0296c);
863 yi
->reg_2970
= read_reg(0x02970);
869 /* Set some valid size info */
870 yi
->osd_x_offset
= read_reg(0x02a04) & 0x00000FFF;
871 yi
->osd_y_offset
= (read_reg(0x02a04) >> 16) & 0x00000FFF;
873 /* Bit 2 of reg 2878 indicates current decoder output format
875 if (read_reg(0x2878) & 4)
876 yi
->decode_height
= 576;
878 yi
->decode_height
= 480;
880 if (!itv
->osd_info
) {
881 yi
->osd_vis_w
= 720 - yi
->osd_x_offset
;
882 yi
->osd_vis_h
= yi
->decode_height
- yi
->osd_y_offset
;
884 /* If no visible size set, assume full size */
886 yi
->osd_vis_w
= 720 - yi
->osd_x_offset
;
888 if (!yi
->osd_vis_h
) {
889 yi
->osd_vis_h
= yi
->decode_height
- yi
->osd_y_offset
;
890 } else if (yi
->osd_vis_h
+ yi
->osd_y_offset
> yi
->decode_height
) {
891 /* If output video standard has changed, requested height may
893 IVTV_DEBUG_WARN("Clipping yuv output - fb size (%d) exceeds video standard limit (%d)\n",
894 yi
->osd_vis_h
+ yi
->osd_y_offset
,
896 yi
->osd_vis_h
= yi
->decode_height
- yi
->osd_y_offset
;
900 /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */
901 yi
->blanking_ptr
= kzalloc(720 * 16, GFP_KERNEL
);
902 if (yi
->blanking_ptr
) {
903 yi
->blanking_dmaptr
= pci_map_single(itv
->dev
, yi
->blanking_ptr
, 720*16, PCI_DMA_TODEVICE
);
905 yi
->blanking_dmaptr
= 0;
906 IVTV_DEBUG_WARN("Failed to allocate yuv blanking buffer\n");
909 /* Enable YUV decoder output */
910 write_reg_sync(0x01, IVTV_REG_VDM
);
912 set_bit(IVTV_F_I_DECODING_YUV
, &itv
->i_flags
);
913 atomic_set(&yi
->next_dma_frame
, 0);
916 /* Get next available yuv buffer on PVR350 */
917 void ivtv_yuv_next_free(struct ivtv
*itv
)
920 struct yuv_playback_info
*yi
= &itv
->yuv_info
;
922 if (atomic_read(&yi
->next_dma_frame
) == -1)
925 draw
= atomic_read(&yi
->next_fill_frame
);
926 display
= atomic_read(&yi
->next_dma_frame
);
929 display
-= IVTV_YUV_BUFFERS
;
931 if (draw
- display
>= yi
->max_frames_buffered
)
932 draw
= (u8
)(draw
- 1) % IVTV_YUV_BUFFERS
;
934 yi
->new_frame_info
[draw
].update
= 0;
936 yi
->draw_frame
= draw
;
939 /* Set up frame according to ivtv_dma_frame parameters */
940 void ivtv_yuv_setup_frame(struct ivtv
*itv
, struct ivtv_dma_frame
*args
)
942 struct yuv_playback_info
*yi
= &itv
->yuv_info
;
943 u8 frame
= yi
->draw_frame
;
944 u8 last_frame
= (u8
)(frame
- 1) % IVTV_YUV_BUFFERS
;
945 struct yuv_frame_info
*nf
= &yi
->new_frame_info
[frame
];
946 struct yuv_frame_info
*of
= &yi
->new_frame_info
[last_frame
];
947 int lace_threshold
= yi
->lace_threshold
;
949 /* Preserve old update flag in case we're overwriting a queued frame */
950 int update
= nf
->update
;
952 /* Take a snapshot of the yuv coordinate information */
953 nf
->src_x
= args
->src
.left
;
954 nf
->src_y
= args
->src
.top
;
955 nf
->src_w
= args
->src
.width
;
956 nf
->src_h
= args
->src
.height
;
957 nf
->dst_x
= args
->dst
.left
;
958 nf
->dst_y
= args
->dst
.top
;
959 nf
->dst_w
= args
->dst
.width
;
960 nf
->dst_h
= args
->dst
.height
;
961 nf
->tru_x
= args
->dst
.left
;
962 nf
->tru_w
= args
->src_width
;
963 nf
->tru_h
= args
->src_height
;
965 /* Are we going to offset the Y plane */
966 nf
->offset_y
= (nf
->tru_h
+ nf
->src_x
< 512 - 16) ? 1 : 0;
968 /* Snapshot the osd pan info */
969 nf
->pan_x
= yi
->osd_x_pan
;
970 nf
->pan_y
= yi
->osd_y_pan
;
971 nf
->vis_w
= yi
->osd_vis_w
;
972 nf
->vis_h
= yi
->osd_vis_h
;
975 nf
->interlaced_y
= 0;
976 nf
->interlaced_uv
= 0;
979 nf
->lace_mode
= yi
->lace_mode
& IVTV_YUV_MODE_MASK
;
981 if (lace_threshold
< 0)
982 lace_threshold
= yi
->decode_height
- 1;
984 /* Work out the lace settings */
985 switch (nf
->lace_mode
) {
986 case IVTV_YUV_MODE_PROGRESSIVE
: /* Progressive mode */
988 if (nf
->tru_h
< 512 || (nf
->tru_h
> 576 && nf
->tru_h
< 1021))
989 nf
->interlaced_y
= 0;
991 nf
->interlaced_y
= 1;
993 if (nf
->tru_h
< 1021 && (nf
->dst_h
>= nf
->src_h
/ 2))
994 nf
->interlaced_uv
= 0;
996 nf
->interlaced_uv
= 1;
999 case IVTV_YUV_MODE_AUTO
:
1000 if (nf
->tru_h
<= lace_threshold
|| nf
->tru_h
> 576 || nf
->tru_w
> 720) {
1002 if ((nf
->tru_h
< 512) ||
1003 (nf
->tru_h
> 576 && nf
->tru_h
< 1021) ||
1004 (nf
->tru_w
> 720 && nf
->tru_h
< 1021))
1005 nf
->interlaced_y
= 0;
1007 nf
->interlaced_y
= 1;
1008 if (nf
->tru_h
< 1021 && (nf
->dst_h
>= nf
->src_h
/ 2))
1009 nf
->interlaced_uv
= 0;
1011 nf
->interlaced_uv
= 1;
1014 nf
->interlaced_y
= 1;
1015 nf
->interlaced_uv
= 1;
1019 case IVTV_YUV_MODE_INTERLACED
: /* Interlace mode */
1022 nf
->interlaced_y
= 1;
1023 nf
->interlaced_uv
= 1;
1027 if (memcmp(&yi
->old_frame_info_args
, nf
, sizeof(*nf
))) {
1028 yi
->old_frame_info_args
= *nf
;
1030 IVTV_DEBUG_YUV("Requesting reg update for frame %d\n", frame
);
1033 nf
->update
|= update
;
1034 nf
->sync_field
= yi
->lace_sync_field
;
1035 nf
->delay
= nf
->sync_field
!= of
->sync_field
;
1038 /* Frame is complete & ready for display */
1039 void ivtv_yuv_frame_complete(struct ivtv
*itv
)
1041 atomic_set(&itv
->yuv_info
.next_fill_frame
,
1042 (itv
->yuv_info
.draw_frame
+ 1) % IVTV_YUV_BUFFERS
);
1045 int ivtv_yuv_udma_frame(struct ivtv
*itv
, struct ivtv_dma_frame
*args
)
1051 mutex_lock(&itv
->udma
.lock
);
1053 if ((rc
= ivtv_yuv_prep_user_dma(itv
, &itv
->udma
, args
)) != 0) {
1054 mutex_unlock(&itv
->udma
.lock
);
1058 ivtv_udma_prepare(itv
);
1059 prepare_to_wait(&itv
->dma_waitq
, &wait
, TASK_INTERRUPTIBLE
);
1060 /* if no UDMA is pending and no UDMA is in progress, then the DMA
1062 while (itv
->i_flags
& (IVTV_F_I_UDMA_PENDING
| IVTV_F_I_UDMA
)) {
1063 /* don't interrupt if the DMA is in progress but break off
1064 a still pending DMA. */
1065 got_sig
= signal_pending(current
);
1066 if (got_sig
&& test_and_clear_bit(IVTV_F_I_UDMA_PENDING
, &itv
->i_flags
))
1071 finish_wait(&itv
->dma_waitq
, &wait
);
1073 /* Unmap Last DMA Xfer */
1074 ivtv_udma_unmap(itv
);
1077 IVTV_DEBUG_INFO("User stopped YUV UDMA\n");
1078 mutex_unlock(&itv
->udma
.lock
);
1082 ivtv_yuv_frame_complete(itv
);
1084 mutex_unlock(&itv
->udma
.lock
);
1088 /* Setup frame according to V4L2 parameters */
1089 void ivtv_yuv_setup_stream_frame(struct ivtv
*itv
)
1091 struct yuv_playback_info
*yi
= &itv
->yuv_info
;
1092 struct ivtv_dma_frame dma_args
;
1094 ivtv_yuv_next_free(itv
);
1096 /* Copy V4L2 parameters to an ivtv_dma_frame struct... */
1097 dma_args
.y_source
= 0L;
1098 dma_args
.uv_source
= 0L;
1099 dma_args
.src
.left
= 0;
1100 dma_args
.src
.top
= 0;
1101 dma_args
.src
.width
= yi
->v4l2_src_w
;
1102 dma_args
.src
.height
= yi
->v4l2_src_h
;
1103 dma_args
.dst
= yi
->main_rect
;
1104 dma_args
.src_width
= yi
->v4l2_src_w
;
1105 dma_args
.src_height
= yi
->v4l2_src_h
;
1107 /* ... and use the same setup routine as ivtv_yuv_prep_frame */
1108 ivtv_yuv_setup_frame(itv
, &dma_args
);
1110 if (!itv
->dma_data_req_offset
)
1111 itv
->dma_data_req_offset
= yuv_offset
[yi
->draw_frame
];
1114 /* Attempt to dma a frame from a user buffer */
1115 int ivtv_yuv_udma_stream_frame(struct ivtv
*itv
, void *src
)
1117 struct yuv_playback_info
*yi
= &itv
->yuv_info
;
1118 struct ivtv_dma_frame dma_args
;
1120 ivtv_yuv_setup_stream_frame(itv
);
1122 /* We only need to supply source addresses for this */
1123 dma_args
.y_source
= src
;
1124 dma_args
.uv_source
= src
+ 720 * ((yi
->v4l2_src_h
+ 31) & ~31);
1125 return ivtv_yuv_udma_frame(itv
, &dma_args
);
1128 /* IVTV_IOC_DMA_FRAME ioctl handler */
1129 int ivtv_yuv_prep_frame(struct ivtv
*itv
, struct ivtv_dma_frame
*args
)
1131 /* IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
1133 ivtv_yuv_next_free(itv
);
1134 ivtv_yuv_setup_frame(itv
, args
);
1135 return ivtv_yuv_udma_frame(itv
, args
);
1138 void ivtv_yuv_close(struct ivtv
*itv
)
1140 struct yuv_playback_info
*yi
= &itv
->yuv_info
;
1141 int h_filter
, v_filter_1
, v_filter_2
;
1143 IVTV_DEBUG_YUV("ivtv_yuv_close\n");
1144 ivtv_waitq(&itv
->vsync_waitq
);
1146 atomic_set(&yi
->next_dma_frame
, -1);
1147 atomic_set(&yi
->next_fill_frame
, 0);
1149 /* Reset registers we have changed so mpeg playback works */
1151 /* If we fully restore this register, the display may remain active.
1152 Restore, but set one bit to blank the video. Firmware will always
1153 clear this bit when needed, so not a problem. */
1154 write_reg(yi
->reg_2898
| 0x01000000, 0x2898);
1156 write_reg(yi
->reg_2834
, 0x02834);
1157 write_reg(yi
->reg_2838
, 0x02838);
1158 write_reg(yi
->reg_283c
, 0x0283c);
1159 write_reg(yi
->reg_2840
, 0x02840);
1160 write_reg(yi
->reg_2844
, 0x02844);
1161 write_reg(yi
->reg_2848
, 0x02848);
1162 write_reg(yi
->reg_2854
, 0x02854);
1163 write_reg(yi
->reg_285c
, 0x0285c);
1164 write_reg(yi
->reg_2864
, 0x02864);
1165 write_reg(yi
->reg_2870
, 0x02870);
1166 write_reg(yi
->reg_2874
, 0x02874);
1167 write_reg(yi
->reg_2890
, 0x02890);
1168 write_reg(yi
->reg_289c
, 0x0289c);
1170 write_reg(yi
->reg_2918
, 0x02918);
1171 write_reg(yi
->reg_291c
, 0x0291c);
1172 write_reg(yi
->reg_2920
, 0x02920);
1173 write_reg(yi
->reg_2924
, 0x02924);
1174 write_reg(yi
->reg_2928
, 0x02928);
1175 write_reg(yi
->reg_292c
, 0x0292c);
1176 write_reg(yi
->reg_2930
, 0x02930);
1177 write_reg(yi
->reg_2934
, 0x02934);
1178 write_reg(yi
->reg_2938
, 0x02938);
1179 write_reg(yi
->reg_293c
, 0x0293c);
1180 write_reg(yi
->reg_2940
, 0x02940);
1181 write_reg(yi
->reg_2944
, 0x02944);
1182 write_reg(yi
->reg_2948
, 0x02948);
1183 write_reg(yi
->reg_294c
, 0x0294c);
1184 write_reg(yi
->reg_2950
, 0x02950);
1185 write_reg(yi
->reg_2954
, 0x02954);
1186 write_reg(yi
->reg_2958
, 0x02958);
1187 write_reg(yi
->reg_295c
, 0x0295c);
1188 write_reg(yi
->reg_2960
, 0x02960);
1189 write_reg(yi
->reg_2964
, 0x02964);
1190 write_reg(yi
->reg_2968
, 0x02968);
1191 write_reg(yi
->reg_296c
, 0x0296c);
1192 write_reg(yi
->reg_2970
, 0x02970);
1194 /* Prepare to restore filters */
1196 /* First the horizontal filter */
1197 if ((yi
->reg_2834
& 0x0000FFFF) == (yi
->reg_2834
>> 16)) {
1198 /* An exact size match uses filter 0 */
1201 /* Figure out which filter to use */
1202 h_filter
= ((yi
->reg_2834
<< 16) / (yi
->reg_2834
>> 16)) >> 15;
1203 h_filter
= (h_filter
>> 1) + (h_filter
& 1);
1204 /* Only an exact size match can use filter 0. */
1205 h_filter
+= !h_filter
;
1208 /* Now the vertical filter */
1209 if ((yi
->reg_2918
& 0x0000FFFF) == (yi
->reg_2918
>> 16)) {
1210 /* An exact size match uses filter 0/1 */
1214 /* Figure out which filter to use */
1215 v_filter_1
= ((yi
->reg_2918
<< 16) / (yi
->reg_2918
>> 16)) >> 15;
1216 v_filter_1
= (v_filter_1
>> 1) + (v_filter_1
& 1);
1217 /* Only an exact size match can use filter 0 */
1218 v_filter_1
+= !v_filter_1
;
1219 v_filter_2
= v_filter_1
;
1222 /* Now restore the filters */
1223 ivtv_yuv_filter(itv
, h_filter
, v_filter_1
, v_filter_2
);
1225 /* and clear a few registers */
1226 write_reg(0, 0x02814);
1227 write_reg(0, 0x0282c);
1228 write_reg(0, 0x02904);
1229 write_reg(0, 0x02910);
1231 /* Release the blanking buffer */
1232 if (yi
->blanking_ptr
) {
1233 kfree(yi
->blanking_ptr
);
1234 yi
->blanking_ptr
= NULL
;
1235 pci_unmap_single(itv
->dev
, yi
->blanking_dmaptr
, 720*16, PCI_DMA_TODEVICE
);
1238 /* Invalidate the old dimension information */
1239 yi
->old_frame_info
.src_w
= 0;
1240 yi
->old_frame_info
.src_h
= 0;
1241 yi
->old_frame_info_args
.src_w
= 0;
1242 yi
->old_frame_info_args
.src_h
= 0;
1245 clear_bit(IVTV_F_I_DECODING_YUV
, &itv
->i_flags
);