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-queue.h"
23 #include "ivtv-udma.h"
27 static int ivtv_yuv_prep_user_dma(struct ivtv
*itv
, struct ivtv_user_dma
*dma
,
28 struct ivtv_dma_frame
*args
)
30 struct ivtv_dma_page_info y_dma
;
31 struct ivtv_dma_page_info uv_dma
;
34 int y_pages
, uv_pages
;
36 unsigned long y_buffer_offset
, uv_buffer_offset
;
37 int y_decode_height
, uv_decode_height
, y_size
;
38 int frame
= atomic_read(&itv
->yuv_info
.next_fill_frame
);
40 y_buffer_offset
= IVTV_DEC_MEM_START
+ yuv_offset
[frame
];
41 uv_buffer_offset
= y_buffer_offset
+ IVTV_YUV_BUFFER_UV_OFFSET
;
43 y_decode_height
= uv_decode_height
= args
->src
.height
+ args
->src
.top
;
45 if (y_decode_height
< 512-16)
46 y_buffer_offset
+= 720 * 16;
48 if (y_decode_height
& 15)
49 y_decode_height
= (y_decode_height
+ 16) & ~15;
51 if (uv_decode_height
& 31)
52 uv_decode_height
= (uv_decode_height
+ 32) & ~31;
54 y_size
= 720 * y_decode_height
;
57 if (dma
->SG_length
|| dma
->page_count
) {
58 IVTV_DEBUG_WARN("prep_user_dma: SG_length %d page_count %d still full?\n",
59 dma
->SG_length
, dma
->page_count
);
63 ivtv_udma_get_page_info (&y_dma
, (unsigned long)args
->y_source
, 720 * y_decode_height
);
64 ivtv_udma_get_page_info (&uv_dma
, (unsigned long)args
->uv_source
, 360 * uv_decode_height
);
66 /* Get user pages for DMA Xfer */
67 down_read(¤t
->mm
->mmap_sem
);
68 y_pages
= get_user_pages(current
, current
->mm
, y_dma
.uaddr
, y_dma
.page_count
, 0, 1, &dma
->map
[0], NULL
);
69 uv_pages
= get_user_pages(current
, current
->mm
, uv_dma
.uaddr
, uv_dma
.page_count
, 0, 1, &dma
->map
[y_pages
], NULL
);
70 up_read(¤t
->mm
->mmap_sem
);
72 dma
->page_count
= y_dma
.page_count
+ uv_dma
.page_count
;
74 if (y_pages
+ uv_pages
!= dma
->page_count
) {
75 IVTV_DEBUG_WARN("failed to map user pages, returned %d instead of %d\n",
76 y_pages
+ uv_pages
, dma
->page_count
);
78 for (i
= 0; i
< dma
->page_count
; i
++) {
79 put_page(dma
->map
[i
]);
85 /* Fill & map SG List */
86 ivtv_udma_fill_sg_list (dma
, &uv_dma
, ivtv_udma_fill_sg_list (dma
, &y_dma
, 0));
87 dma
->SG_length
= pci_map_sg(itv
->dev
, dma
->SGlist
, dma
->page_count
, PCI_DMA_TODEVICE
);
89 /* Fill SG Array with new values */
90 ivtv_udma_fill_sg_array (dma
, y_buffer_offset
, uv_buffer_offset
, y_size
);
92 /* If we've offset the y plane, ensure top area is blanked */
93 if (args
->src
.height
+ args
->src
.top
< 512-16) {
94 if (itv
->yuv_info
.blanking_dmaptr
) {
95 dma
->SGarray
[dma
->SG_length
].size
= cpu_to_le32(720*16);
96 dma
->SGarray
[dma
->SG_length
].src
= cpu_to_le32(itv
->yuv_info
.blanking_dmaptr
);
97 dma
->SGarray
[dma
->SG_length
].dst
= cpu_to_le32(IVTV_DEC_MEM_START
+ yuv_offset
[frame
]);
102 /* Tag SG Array with Interrupt Bit */
103 dma
->SGarray
[dma
->SG_length
- 1].size
|= cpu_to_le32(0x80000000);
105 ivtv_udma_sync_for_device(itv
);
109 /* We rely on a table held in the firmware - Quick check. */
110 int ivtv_yuv_filter_check(struct ivtv
*itv
)
112 int i
, offset_y
, offset_uv
;
114 for (i
=0, offset_y
= 16, offset_uv
= 4; i
<16; i
++, offset_y
+= 24, offset_uv
+= 12) {
115 if ((read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET
+ offset_y
) != i
<< 16) ||
116 (read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET
+ offset_uv
) != i
<< 16)) {
117 IVTV_WARN ("YUV filter table not found in firmware.\n");
124 static void ivtv_yuv_filter(struct ivtv
*itv
, int h_filter
, int v_filter_1
, int v_filter_2
)
126 int filter_index
, filter_line
;
128 /* If any filter is -1, then don't update it */
130 if (h_filter
> 4) h_filter
= 4;
131 filter_index
= h_filter
* 384;
133 while (filter_line
< 16) {
134 write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET
+ filter_index
), 0x02804);
135 write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET
+ filter_index
), 0x0281c);
137 write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET
+ filter_index
), 0x02808);
138 write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET
+ filter_index
), 0x02820);
140 write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET
+ filter_index
), 0x0280c);
141 write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET
+ filter_index
), 0x02824);
143 write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET
+ filter_index
), 0x02810);
144 write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET
+ filter_index
), 0x02828);
146 write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET
+ filter_index
), 0x02814);
147 write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET
+ filter_index
), 0x0282c);
149 write_reg(0, 0x02818);
150 write_reg(0, 0x02830);
153 IVTV_DEBUG_YUV("h_filter -> %d\n",h_filter
);
156 if (v_filter_1
> -1) {
157 if (v_filter_1
> 4) v_filter_1
= 4;
158 filter_index
= v_filter_1
* 192;
160 while (filter_line
< 16) {
161 write_reg(read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET
+ filter_index
), 0x02900);
163 write_reg(read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET
+ filter_index
), 0x02904);
165 write_reg(0, 0x02908);
168 IVTV_DEBUG_YUV("v_filter_1 -> %d\n",v_filter_1
);
171 if (v_filter_2
> -1) {
172 if (v_filter_2
> 4) v_filter_2
= 4;
173 filter_index
= v_filter_2
* 192;
175 while (filter_line
< 16) {
176 write_reg(read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET
+ filter_index
), 0x0290c);
178 write_reg(read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET
+ filter_index
), 0x02910);
180 write_reg(0, 0x02914);
183 IVTV_DEBUG_YUV("v_filter_2 -> %d\n",v_filter_2
);
187 static void ivtv_yuv_handle_horizontal(struct ivtv
*itv
, struct yuv_frame_info
*window
)
189 u32 reg_2834
, reg_2838
, reg_283c
;
190 u32 reg_2844
, reg_2854
, reg_285c
;
191 u32 reg_2864
, reg_2874
, reg_2890
;
192 u32 reg_2870
, reg_2870_base
, reg_2870_offset
;
197 IVTV_DEBUG_WARN( "Need to adjust to width %d src_w %d dst_w %d src_x %d dst_x %d\n",
198 window
->tru_w
, window
->src_w
, window
->dst_w
,window
->src_x
, window
->dst_x
);
200 /* How wide is the src image */
201 x_cutoff
= window
->src_w
+ window
->src_x
;
203 /* Set the display width */
204 reg_2834
= window
->dst_w
;
207 /* Set the display position */
208 reg_2890
= window
->dst_x
;
210 /* Index into the image horizontally */
213 /* 2870 is normally fudged to align video coords with osd coords.
214 If running full screen, it causes an unwanted left shift
215 Remove the fudge if we almost fill the screen.
216 Gradually adjust the offset to avoid the video 'snapping'
217 left/right if it gets dragged through this region.
218 Only do this if osd is full width. */
219 if (window
->vis_w
== 720) {
220 if ((window
->tru_x
- window
->pan_x
> -1) && (window
->tru_x
- window
->pan_x
<= 40) && (window
->dst_w
>= 680)){
221 reg_2870
= 10 - (window
->tru_x
- window
->pan_x
) / 4;
223 else if ((window
->tru_x
- window
->pan_x
< 0) && (window
->tru_x
- window
->pan_x
>= -20) && (window
->dst_w
>= 660)) {
224 reg_2870
= (10 + (window
->tru_x
- window
->pan_x
) / 2);
227 if (window
->dst_w
>= window
->src_w
)
228 reg_2870
= reg_2870
<< 16 | reg_2870
;
230 reg_2870
= ((reg_2870
& ~1) << 15) | (reg_2870
& ~1);
233 if (window
->dst_w
< window
->src_w
)
234 reg_2870
= 0x000d000e - reg_2870
;
236 reg_2870
= 0x0012000e - reg_2870
;
238 /* We're also using 2870 to shift the image left (src_x & negative dst_x) */
239 reg_2870_offset
= (window
->src_x
*((window
->dst_w
<< 21)/window
->src_w
))>>19;
241 if (window
->dst_w
>= window
->src_w
) {
243 master_width
= (window
->src_w
* 0x00200000) / (window
->dst_w
);
244 if (master_width
* window
->dst_w
!= window
->src_w
* 0x00200000) master_width
++;
245 reg_2834
= (reg_2834
<< 16) | x_cutoff
;
246 reg_2838
= (reg_2838
<< 16) | x_cutoff
;
247 reg_283c
= master_width
>> 2;
248 reg_2844
= master_width
>> 2;
249 reg_2854
= master_width
;
250 reg_285c
= master_width
>> 1;
251 reg_2864
= master_width
>> 1;
253 /* We also need to factor in the scaling
254 (src_w - dst_w) / (src_w / 4) */
255 if (window
->dst_w
> window
->src_w
)
256 reg_2870_base
= ((window
->dst_w
- window
->src_w
)<<16) / (window
->src_w
<<14);
260 reg_2870
+= (((reg_2870_offset
<< 14) & 0xFFFF0000) | reg_2870_offset
>> 2) + (reg_2870_base
<< 17 | reg_2870_base
);
263 else if (window
->dst_w
< window
->src_w
/ 2) {
264 master_width
= (window
->src_w
* 0x00080000) / window
->dst_w
;
265 if (master_width
* window
->dst_w
!= window
->src_w
* 0x00080000) master_width
++;
266 reg_2834
= (reg_2834
<< 16) | x_cutoff
;
267 reg_2838
= (reg_2838
<< 16) | x_cutoff
;
268 reg_283c
= master_width
>> 2;
269 reg_2844
= master_width
>> 1;
270 reg_2854
= master_width
;
271 reg_285c
= master_width
>> 1;
272 reg_2864
= master_width
>> 1;
273 reg_2870
+= (((reg_2870_offset
<< 15) & 0xFFFF0000) | reg_2870_offset
);
274 reg_2870
+= (5 - (((window
->src_w
+ window
->src_w
/ 2) - 1) / window
->dst_w
)) << 16;
275 reg_2874
= 0x00000012;
278 master_width
= (window
->src_w
* 0x00100000) / window
->dst_w
;
279 if (master_width
* window
->dst_w
!= window
->src_w
* 0x00100000) master_width
++;
280 reg_2834
= (reg_2834
<< 16) | x_cutoff
;
281 reg_2838
= (reg_2838
<< 16) | x_cutoff
;
282 reg_283c
= master_width
>> 2;
283 reg_2844
= master_width
>> 1;
284 reg_2854
= master_width
;
285 reg_285c
= master_width
>> 1;
286 reg_2864
= master_width
>> 1;
287 reg_2870
+= (((reg_2870_offset
<< 14) & 0xFFFF0000) | reg_2870_offset
>> 1);
288 reg_2870
+= (5 - (((window
->src_w
* 3) - 1) / window
->dst_w
)) << 16;
289 reg_2874
= 0x00000001;
292 /* Select the horizontal filter */
293 if (window
->src_w
== window
->dst_w
) {
294 /* An exact size match uses filter 0 */
298 /* Figure out which filter to use */
299 h_filter
= ((window
->src_w
<< 16) / window
->dst_w
) >> 15;
300 h_filter
= (h_filter
>> 1) + (h_filter
& 1);
301 /* Only an exact size match can use filter 0 */
302 if (h_filter
== 0) h_filter
= 1;
305 write_reg(reg_2834
, 0x02834);
306 write_reg(reg_2838
, 0x02838);
307 IVTV_DEBUG_YUV("Update reg 0x2834 %08x->%08x 0x2838 %08x->%08x\n",itv
->yuv_info
.reg_2834
, reg_2834
, itv
->yuv_info
.reg_2838
, reg_2838
);
309 write_reg(reg_283c
, 0x0283c);
310 write_reg(reg_2844
, 0x02844);
312 IVTV_DEBUG_YUV("Update reg 0x283c %08x->%08x 0x2844 %08x->%08x\n",itv
->yuv_info
.reg_283c
, reg_283c
, itv
->yuv_info
.reg_2844
, reg_2844
);
314 write_reg(0x00080514, 0x02840);
315 write_reg(0x00100514, 0x02848);
316 IVTV_DEBUG_YUV("Update reg 0x2840 %08x->%08x 0x2848 %08x->%08x\n",itv
->yuv_info
.reg_2840
, 0x00080514, itv
->yuv_info
.reg_2848
, 0x00100514);
318 write_reg(reg_2854
, 0x02854);
319 IVTV_DEBUG_YUV("Update reg 0x2854 %08x->%08x \n",itv
->yuv_info
.reg_2854
, reg_2854
);
321 write_reg(reg_285c
, 0x0285c);
322 write_reg(reg_2864
, 0x02864);
323 IVTV_DEBUG_YUV("Update reg 0x285c %08x->%08x 0x2864 %08x->%08x\n",itv
->yuv_info
.reg_285c
, reg_285c
, itv
->yuv_info
.reg_2864
, reg_2864
);
325 write_reg(reg_2874
, 0x02874);
326 IVTV_DEBUG_YUV("Update reg 0x2874 %08x->%08x\n",itv
->yuv_info
.reg_2874
, reg_2874
);
328 write_reg(reg_2870
, 0x02870);
329 IVTV_DEBUG_YUV("Update reg 0x2870 %08x->%08x\n",itv
->yuv_info
.reg_2870
, reg_2870
);
331 write_reg( reg_2890
,0x02890);
332 IVTV_DEBUG_YUV("Update reg 0x2890 %08x->%08x\n",itv
->yuv_info
.reg_2890
, reg_2890
);
334 /* Only update the filter if we really need to */
335 if (h_filter
!= itv
->yuv_info
.h_filter
) {
336 ivtv_yuv_filter (itv
,h_filter
,-1,-1);
337 itv
->yuv_info
.h_filter
= h_filter
;
341 static void ivtv_yuv_handle_vertical(struct ivtv
*itv
, struct yuv_frame_info
*window
)
344 u32 reg_2918
, reg_291c
, reg_2920
, reg_2928
;
345 u32 reg_2930
, reg_2934
, reg_293c
;
346 u32 reg_2940
, reg_2944
, reg_294c
;
347 u32 reg_2950
, reg_2954
, reg_2958
, reg_295c
;
348 u32 reg_2960
, reg_2964
, reg_2968
, reg_296c
;
350 u32 src_y_major_y
, src_y_minor_y
;
351 u32 src_y_major_uv
, src_y_minor_uv
;
352 u32 reg_2964_base
, reg_2968_base
;
353 int v_filter_1
, v_filter_2
;
355 IVTV_DEBUG_WARN("Need to adjust to height %d src_h %d dst_h %d src_y %d dst_y %d\n",
356 window
->tru_h
, window
->src_h
, window
->dst_h
,window
->src_y
, window
->dst_y
);
358 /* What scaling mode is being used... */
359 if (window
->interlaced_y
) {
360 IVTV_DEBUG_YUV("Scaling mode Y: Interlaced\n");
363 IVTV_DEBUG_YUV("Scaling mode Y: Progressive\n");
366 if (window
->interlaced_uv
) {
367 IVTV_DEBUG_YUV("Scaling mode UV: Interlaced\n");
370 IVTV_DEBUG_YUV("Scaling mode UV: Progressive\n");
373 /* What is the source video being treated as... */
374 if (itv
->yuv_info
.frame_interlaced
) {
375 IVTV_DEBUG_WARN("Source video: Interlaced\n");
378 IVTV_DEBUG_WARN("Source video: Non-interlaced\n");
381 /* We offset into the image using two different index methods, so split
382 the y source coord into two parts. */
383 if (window
->src_y
< 8) {
384 src_y_minor_uv
= window
->src_y
;
389 src_y_major_uv
= window
->src_y
- 8;
392 src_y_minor_y
= src_y_minor_uv
;
393 src_y_major_y
= src_y_major_uv
;
395 if (window
->offset_y
) src_y_minor_y
+= 16;
397 if (window
->interlaced_y
)
398 reg_2918
= (window
->dst_h
<< 16) | (window
->src_h
+ src_y_minor_y
);
400 reg_2918
= (window
->dst_h
<< 16) | ((window
->src_h
+ src_y_minor_y
) << 1);
402 if (window
->interlaced_uv
)
403 reg_291c
= (window
->dst_h
<< 16) | ((window
->src_h
+ src_y_minor_uv
) >> 1);
405 reg_291c
= (window
->dst_h
<< 16) | (window
->src_h
+ src_y_minor_uv
);
407 reg_2964_base
= (src_y_minor_y
* ((window
->dst_h
<< 16)/window
->src_h
)) >> 14;
408 reg_2968_base
= (src_y_minor_uv
* ((window
->dst_h
<< 16)/window
->src_h
)) >> 14;
410 if (window
->dst_h
/ 2 >= window
->src_h
&& !window
->interlaced_y
) {
411 master_height
= (window
->src_h
* 0x00400000) / window
->dst_h
;
412 if ((window
->src_h
* 0x00400000) - (master_height
* window
->dst_h
) >= window
->dst_h
/ 2) master_height
++;
413 reg_2920
= master_height
>> 2;
414 reg_2928
= master_height
>> 3;
415 reg_2930
= master_height
;
416 reg_2940
= master_height
>> 1;
419 reg_296c
= 0x00000000;
421 else if (window
->dst_h
>= window
->src_h
) {
422 master_height
= (window
->src_h
* 0x00400000) / window
->dst_h
;
423 master_height
= (master_height
>> 1) + (master_height
& 1);
424 reg_2920
= master_height
>> 2;
425 reg_2928
= master_height
>> 2;
426 reg_2930
= master_height
;
427 reg_2940
= master_height
>> 1;
428 reg_296c
= 0x00000000;
429 if (window
->interlaced_y
) {
436 if (window
->interlaced_uv
) reg_2928
>>= 1;
439 else if (window
->dst_h
>= window
->src_h
/ 2) {
440 master_height
= (window
->src_h
* 0x00200000) / window
->dst_h
;
441 master_height
= (master_height
>> 1) + (master_height
& 1);
442 reg_2920
= master_height
>> 2;
443 reg_2928
= master_height
>> 2;
444 reg_2930
= master_height
;
445 reg_2940
= master_height
;
446 reg_296c
= 0x00000101;
447 if (window
->interlaced_y
) {
454 if (window
->interlaced_uv
) reg_2928
>>= 1;
458 master_height
= (window
->src_h
* 0x00100000) / window
->dst_h
;
459 master_height
= (master_height
>> 1) + (master_height
& 1);
460 reg_2920
= master_height
>> 2;
461 reg_2928
= master_height
>> 2;
462 reg_2930
= master_height
;
463 reg_2940
= master_height
;
466 reg_296c
= 0x00000102;
469 /* FIXME These registers change depending on scaled / unscaled output
470 We really need to work out what they should be */
471 if (window
->src_h
== window
->dst_h
){
472 reg_2934
= 0x00020000;
473 reg_293c
= 0x00100000;
474 reg_2944
= 0x00040000;
475 reg_294c
= 0x000b0000;
478 reg_2934
= 0x00000FF0;
479 reg_293c
= 0x00000FF0;
480 reg_2944
= 0x00000FF0;
481 reg_294c
= 0x00000FF0;
484 /* The first line to be displayed */
485 reg_2950
= 0x00010000 + src_y_major_y
;
486 if (window
->interlaced_y
) reg_2950
+= 0x00010000;
487 reg_2954
= reg_2950
+ 1;
489 reg_2958
= 0x00010000 + (src_y_major_y
>> 1);
490 if (window
->interlaced_uv
) reg_2958
+= 0x00010000;
491 reg_295c
= reg_2958
+ 1;
493 if (itv
->yuv_info
.decode_height
== 480)
494 reg_289c
= 0x011e0017;
496 reg_289c
= 0x01500017;
498 if (window
->dst_y
< 0)
499 reg_289c
= (reg_289c
- ((window
->dst_y
& ~1)<<15))-(window
->dst_y
>>1);
501 reg_289c
= (reg_289c
+ ((window
->dst_y
& ~1)<<15))+(window
->dst_y
>>1);
503 /* How much of the source to decode.
504 Take into account the source offset */
505 reg_2960
= ((src_y_minor_y
+ window
->src_h
+ src_y_major_y
) - 1 ) |
506 ((((src_y_minor_uv
+ window
->src_h
+ src_y_major_uv
) - 1) & ~1) << 15);
508 /* Calculate correct value for register 2964 */
509 if (window
->src_h
== window
->dst_h
)
512 reg_2964
= 2 + ((window
->dst_h
<< 1) / window
->src_h
);
513 reg_2964
= (reg_2964
>> 1) + (reg_2964
& 1);
515 reg_2968
= (reg_2964
<< 16) + reg_2964
+ (reg_2964
>> 1);
516 reg_2964
= (reg_2964
<< 16) + reg_2964
+ (reg_2964
* 46 / 94);
518 /* Okay, we've wasted time working out the correct value,
519 but if we use it, it fouls the the window alignment.
520 Fudge it to what we want... */
521 reg_2964
= 0x00010001 + ((reg_2964
& 0x0000FFFF) - (reg_2964
>> 16));
522 reg_2968
= 0x00010001 + ((reg_2968
& 0x0000FFFF) - (reg_2968
>> 16));
524 /* Deviate further from what it should be. I find the flicker headache
525 inducing so try to reduce it slightly. Leave 2968 as-is otherwise
527 if ((reg_2964
!= 0x00010001) && (window
->dst_h
/ 2 <= window
->src_h
))
528 reg_2964
= (reg_2964
& 0xFFFF0000) + ((reg_2964
& 0x0000FFFF)/2);
530 if (!window
->interlaced_y
) reg_2964
-= 0x00010001;
531 if (!window
->interlaced_uv
) reg_2968
-= 0x00010001;
533 reg_2964
+= ((reg_2964_base
<< 16) | reg_2964_base
);
534 reg_2968
+= ((reg_2968_base
<< 16) | reg_2968_base
);
536 /* Select the vertical filter */
537 if (window
->src_h
== window
->dst_h
) {
538 /* An exact size match uses filter 0/1 */
543 /* Figure out which filter to use */
544 v_filter_1
= ((window
->src_h
<< 16) / window
->dst_h
) >> 15;
545 v_filter_1
= (v_filter_1
>> 1) + (v_filter_1
& 1);
546 /* Only an exact size match can use filter 0 */
547 if (v_filter_1
== 0) v_filter_1
= 1;
548 v_filter_2
= v_filter_1
;
551 write_reg(reg_2934
, 0x02934);
552 write_reg(reg_293c
, 0x0293c);
553 IVTV_DEBUG_YUV("Update reg 0x2934 %08x->%08x 0x293c %08x->%08x\n",itv
->yuv_info
.reg_2934
, reg_2934
, itv
->yuv_info
.reg_293c
, reg_293c
);
554 write_reg(reg_2944
, 0x02944);
555 write_reg(reg_294c
, 0x0294c);
556 IVTV_DEBUG_YUV("Update reg 0x2944 %08x->%08x 0x294c %08x->%08x\n",itv
->yuv_info
.reg_2944
, reg_2944
, itv
->yuv_info
.reg_294c
, reg_294c
);
558 /* Ensure 2970 is 0 (does it ever change ?) */
559 /* write_reg(0,0x02970); */
560 /* IVTV_DEBUG_YUV("Update reg 0x2970 %08x->%08x\n",itv->yuv_info.reg_2970, 0); */
562 write_reg(reg_2930
, 0x02938);
563 write_reg(reg_2930
, 0x02930);
564 IVTV_DEBUG_YUV("Update reg 0x2930 %08x->%08x 0x2938 %08x->%08x\n",itv
->yuv_info
.reg_2930
, reg_2930
, itv
->yuv_info
.reg_2938
, reg_2930
);
566 write_reg(reg_2928
, 0x02928);
567 write_reg(reg_2928
+0x514, 0x0292C);
568 IVTV_DEBUG_YUV("Update reg 0x2928 %08x->%08x 0x292c %08x->%08x\n",itv
->yuv_info
.reg_2928
, reg_2928
, itv
->yuv_info
.reg_292c
, reg_2928
+0x514);
570 write_reg(reg_2920
, 0x02920);
571 write_reg(reg_2920
+0x514, 0x02924);
572 IVTV_DEBUG_YUV("Update reg 0x2920 %08x->%08x 0x2924 %08x->%08x\n",itv
->yuv_info
.reg_2920
, reg_2920
, itv
->yuv_info
.reg_2924
, 0x514+reg_2920
);
574 write_reg (reg_2918
,0x02918);
575 write_reg (reg_291c
,0x0291C);
576 IVTV_DEBUG_YUV("Update reg 0x2918 %08x->%08x 0x291C %08x->%08x\n",itv
->yuv_info
.reg_2918
,reg_2918
,itv
->yuv_info
.reg_291c
,reg_291c
);
578 write_reg(reg_296c
, 0x0296c);
579 IVTV_DEBUG_YUV("Update reg 0x296c %08x->%08x\n",itv
->yuv_info
.reg_296c
, reg_296c
);
581 write_reg(reg_2940
, 0x02948);
582 write_reg(reg_2940
, 0x02940);
583 IVTV_DEBUG_YUV("Update reg 0x2940 %08x->%08x 0x2948 %08x->%08x\n",itv
->yuv_info
.reg_2940
, reg_2940
, itv
->yuv_info
.reg_2948
, reg_2940
);
585 write_reg(reg_2950
, 0x02950);
586 write_reg(reg_2954
, 0x02954);
587 IVTV_DEBUG_YUV("Update reg 0x2950 %08x->%08x 0x2954 %08x->%08x\n",itv
->yuv_info
.reg_2950
, reg_2950
, itv
->yuv_info
.reg_2954
, reg_2954
);
589 write_reg(reg_2958
, 0x02958);
590 write_reg(reg_295c
, 0x0295C);
591 IVTV_DEBUG_YUV("Update reg 0x2958 %08x->%08x 0x295C %08x->%08x\n",itv
->yuv_info
.reg_2958
, reg_2958
, itv
->yuv_info
.reg_295c
, reg_295c
);
593 write_reg(reg_2960
, 0x02960);
594 IVTV_DEBUG_YUV("Update reg 0x2960 %08x->%08x \n",itv
->yuv_info
.reg_2960
, reg_2960
);
596 write_reg(reg_2964
, 0x02964);
597 write_reg(reg_2968
, 0x02968);
598 IVTV_DEBUG_YUV("Update reg 0x2964 %08x->%08x 0x2968 %08x->%08x\n",itv
->yuv_info
.reg_2964
, reg_2964
, itv
->yuv_info
.reg_2968
, reg_2968
);
600 write_reg( reg_289c
,0x0289c);
601 IVTV_DEBUG_YUV("Update reg 0x289c %08x->%08x\n",itv
->yuv_info
.reg_289c
, reg_289c
);
603 /* Only update filter 1 if we really need to */
604 if (v_filter_1
!= itv
->yuv_info
.v_filter_1
) {
605 ivtv_yuv_filter (itv
,-1,v_filter_1
,-1);
606 itv
->yuv_info
.v_filter_1
= v_filter_1
;
609 /* Only update filter 2 if we really need to */
610 if (v_filter_2
!= itv
->yuv_info
.v_filter_2
) {
611 ivtv_yuv_filter (itv
,-1,-1,v_filter_2
);
612 itv
->yuv_info
.v_filter_2
= v_filter_2
;
615 itv
->yuv_info
.frame_interlaced_last
= itv
->yuv_info
.frame_interlaced
;
618 /* Modify the supplied coordinate information to fit the visible osd area */
619 static u32
ivtv_yuv_window_setup (struct ivtv
*itv
, struct yuv_frame_info
*window
)
621 int osd_crop
, lace_threshold
;
625 lace_threshold
= itv
->yuv_info
.lace_threshold
;
626 if (lace_threshold
< 0)
627 lace_threshold
= itv
->yuv_info
.decode_height
- 1;
629 /* Work out the lace settings */
630 switch (itv
->yuv_info
.lace_mode
) {
631 case IVTV_YUV_MODE_PROGRESSIVE
: /* Progressive mode */
632 itv
->yuv_info
.frame_interlaced
= 0;
633 if (window
->tru_h
< 512 || (window
->tru_h
> 576 && window
->tru_h
< 1021))
634 window
->interlaced_y
= 0;
636 window
->interlaced_y
= 1;
638 if (window
->tru_h
< 1021 && (window
->dst_h
>= window
->src_h
/2))
639 window
->interlaced_uv
= 0;
641 window
->interlaced_uv
= 1;
644 case IVTV_YUV_MODE_AUTO
:
645 if (window
->tru_h
<= lace_threshold
|| window
->tru_h
> 576 || window
->tru_w
> 720){
646 itv
->yuv_info
.frame_interlaced
= 0;
647 if ((window
->tru_h
< 512) ||
648 (window
->tru_h
> 576 && window
->tru_h
< 1021) ||
649 (window
->tru_w
> 720 && window
->tru_h
< 1021))
650 window
->interlaced_y
= 0;
652 window
->interlaced_y
= 1;
654 if (window
->tru_h
< 1021 && (window
->dst_h
>= window
->src_h
/2))
655 window
->interlaced_uv
= 0;
657 window
->interlaced_uv
= 1;
660 itv
->yuv_info
.frame_interlaced
= 1;
661 window
->interlaced_y
= 1;
662 window
->interlaced_uv
= 1;
666 case IVTV_YUV_MODE_INTERLACED
: /* Interlace mode */
668 itv
->yuv_info
.frame_interlaced
= 1;
669 window
->interlaced_y
= 1;
670 window
->interlaced_uv
= 1;
674 /* Sorry, but no negative coords for src */
675 if (window
->src_x
< 0) window
->src_x
= 0;
676 if (window
->src_y
< 0) window
->src_y
= 0;
678 /* Can only reduce width down to 1/4 original size */
679 if ((osd_crop
= window
->src_w
- ( 4 * window
->dst_w
)) > 0) {
680 window
->src_x
+= osd_crop
/ 2;
681 window
->src_w
= (window
->src_w
- osd_crop
) & ~3;
682 window
->dst_w
= window
->src_w
/ 4;
683 window
->dst_w
+= window
->dst_w
& 1;
686 /* Can only reduce height down to 1/4 original size */
687 if (window
->src_h
/ window
->dst_h
>= 2) {
688 /* Overflow may be because we're running progressive, so force mode switch */
689 window
->interlaced_y
= 1;
690 /* Make sure we're still within limits for interlace */
691 if ((osd_crop
= window
->src_h
- ( 4 * window
->dst_h
)) > 0) {
692 /* If we reach here we'll have to force the height. */
693 window
->src_y
+= osd_crop
/ 2;
694 window
->src_h
= (window
->src_h
- osd_crop
) & ~3;
695 window
->dst_h
= window
->src_h
/ 4;
696 window
->dst_h
+= window
->dst_h
& 1;
700 /* If there's nothing to safe to display, we may as well stop now */
701 if ((int)window
->dst_w
<= 2 || (int)window
->dst_h
<= 2 || (int)window
->src_w
<= 2 || (int)window
->src_h
<= 2) {
705 /* Ensure video remains inside OSD area */
706 osd_scale
= (window
->src_h
<< 16) / window
->dst_h
;
708 if ((osd_crop
= window
->pan_y
- window
->dst_y
) > 0) {
709 /* Falls off the upper edge - crop */
710 window
->src_y
+= (osd_scale
* osd_crop
) >> 16;
711 window
->src_h
-= (osd_scale
* osd_crop
) >> 16;
712 window
->dst_h
-= osd_crop
;
716 window
->dst_y
-= window
->pan_y
;
719 if ((osd_crop
= window
->dst_h
+ window
->dst_y
- window
->vis_h
) > 0) {
720 /* Falls off the lower edge - crop */
721 window
->dst_h
-= osd_crop
;
722 window
->src_h
-= (osd_scale
* osd_crop
) >> 16;
725 osd_scale
= (window
->src_w
<< 16) / window
->dst_w
;
727 if ((osd_crop
= window
->pan_x
- window
->dst_x
) > 0) {
728 /* Fall off the left edge - crop */
729 window
->src_x
+= (osd_scale
* osd_crop
) >> 16;
730 window
->src_w
-= (osd_scale
* osd_crop
) >> 16;
731 window
->dst_w
-= osd_crop
;
735 window
->dst_x
-= window
->pan_x
;
738 if ((osd_crop
= window
->dst_w
+ window
->dst_x
- window
->vis_w
) > 0) {
739 /* Falls off the right edge - crop */
740 window
->dst_w
-= osd_crop
;
741 window
->src_w
-= (osd_scale
* osd_crop
) >> 16;
744 /* The OSD can be moved. Track to it */
745 window
->dst_x
+= itv
->yuv_info
.osd_x_offset
;
746 window
->dst_y
+= itv
->yuv_info
.osd_y_offset
;
748 /* Width & height for both src & dst must be even.
749 Same for coordinates. */
753 window
->src_w
+= window
->src_x
& 1;
762 window
->src_h
+= window
->src_y
& 1;
768 /* Due to rounding, we may have reduced the output size to <1/4 of the source
769 Check again, but this time just resize. Don't change source coordinates */
770 if (window
->dst_w
< window
->src_w
/ 4) {
772 window
->dst_w
= window
->src_w
/ 4;
773 window
->dst_w
+= window
->dst_w
& 1;
775 if (window
->dst_h
< window
->src_h
/ 4) {
777 window
->dst_h
= window
->src_h
/ 4;
778 window
->dst_h
+= window
->dst_h
& 1;
781 /* Check again. If there's nothing to safe to display, stop now */
782 if ((int)window
->dst_w
<= 2 || (int)window
->dst_h
<= 2 || (int)window
->src_w
<= 2 || (int)window
->src_h
<= 2) {
786 /* Both x offset & width are linked, so they have to be done together */
787 if ((itv
->yuv_info
.old_frame_info
.dst_w
!= window
->dst_w
) ||
788 (itv
->yuv_info
.old_frame_info
.src_w
!= window
->src_w
) ||
789 (itv
->yuv_info
.old_frame_info
.dst_x
!= window
->dst_x
) ||
790 (itv
->yuv_info
.old_frame_info
.src_x
!= window
->src_x
) ||
791 (itv
->yuv_info
.old_frame_info
.pan_x
!= window
->pan_x
) ||
792 (itv
->yuv_info
.old_frame_info
.vis_w
!= window
->vis_w
)) {
793 yuv_update
|= IVTV_YUV_UPDATE_HORIZONTAL
;
796 if ((itv
->yuv_info
.old_frame_info
.src_h
!= window
->src_h
) ||
797 (itv
->yuv_info
.old_frame_info
.dst_h
!= window
->dst_h
) ||
798 (itv
->yuv_info
.old_frame_info
.dst_y
!= window
->dst_y
) ||
799 (itv
->yuv_info
.old_frame_info
.src_y
!= window
->src_y
) ||
800 (itv
->yuv_info
.old_frame_info
.pan_y
!= window
->pan_y
) ||
801 (itv
->yuv_info
.old_frame_info
.vis_h
!= window
->vis_h
) ||
802 (itv
->yuv_info
.old_frame_info
.interlaced_y
!= window
->interlaced_y
) ||
803 (itv
->yuv_info
.old_frame_info
.interlaced_uv
!= window
->interlaced_uv
)) {
804 yuv_update
|= IVTV_YUV_UPDATE_VERTICAL
;
810 /* Update the scaling register to the requested value */
811 void ivtv_yuv_work_handler (struct ivtv
*itv
)
813 struct yuv_frame_info window
;
816 int frame
= itv
->yuv_info
.update_frame
;
818 /* IVTV_DEBUG_YUV("Update yuv registers for frame %d\n",frame); */
819 memcpy(&window
, &itv
->yuv_info
.new_frame_info
[frame
], sizeof (window
));
821 /* Update the osd pan info */
822 window
.pan_x
= itv
->yuv_info
.osd_x_pan
;
823 window
.pan_y
= itv
->yuv_info
.osd_y_pan
;
824 window
.vis_w
= itv
->yuv_info
.osd_vis_w
;
825 window
.vis_h
= itv
->yuv_info
.osd_vis_h
;
827 /* Calculate the display window coordinates. Exit if nothing left */
828 if (!(yuv_update
= ivtv_yuv_window_setup (itv
, &window
)))
831 /* Update horizontal settings */
832 if (yuv_update
& IVTV_YUV_UPDATE_HORIZONTAL
)
833 ivtv_yuv_handle_horizontal(itv
, &window
);
835 if (yuv_update
& IVTV_YUV_UPDATE_VERTICAL
)
836 ivtv_yuv_handle_vertical(itv
, &window
);
838 memcpy(&itv
->yuv_info
.old_frame_info
, &window
, sizeof (itv
->yuv_info
.old_frame_info
));
841 static void ivtv_yuv_init (struct ivtv
*itv
)
843 IVTV_DEBUG_YUV("ivtv_yuv_init\n");
845 /* Take a snapshot of the current register settings */
846 itv
->yuv_info
.reg_2834
= read_reg(0x02834);
847 itv
->yuv_info
.reg_2838
= read_reg(0x02838);
848 itv
->yuv_info
.reg_283c
= read_reg(0x0283c);
849 itv
->yuv_info
.reg_2840
= read_reg(0x02840);
850 itv
->yuv_info
.reg_2844
= read_reg(0x02844);
851 itv
->yuv_info
.reg_2848
= read_reg(0x02848);
852 itv
->yuv_info
.reg_2854
= read_reg(0x02854);
853 itv
->yuv_info
.reg_285c
= read_reg(0x0285c);
854 itv
->yuv_info
.reg_2864
= read_reg(0x02864);
855 itv
->yuv_info
.reg_2870
= read_reg(0x02870);
856 itv
->yuv_info
.reg_2874
= read_reg(0x02874);
857 itv
->yuv_info
.reg_2898
= read_reg(0x02898);
858 itv
->yuv_info
.reg_2890
= read_reg(0x02890);
860 itv
->yuv_info
.reg_289c
= read_reg(0x0289c);
861 itv
->yuv_info
.reg_2918
= read_reg(0x02918);
862 itv
->yuv_info
.reg_291c
= read_reg(0x0291c);
863 itv
->yuv_info
.reg_2920
= read_reg(0x02920);
864 itv
->yuv_info
.reg_2924
= read_reg(0x02924);
865 itv
->yuv_info
.reg_2928
= read_reg(0x02928);
866 itv
->yuv_info
.reg_292c
= read_reg(0x0292c);
867 itv
->yuv_info
.reg_2930
= read_reg(0x02930);
868 itv
->yuv_info
.reg_2934
= read_reg(0x02934);
869 itv
->yuv_info
.reg_2938
= read_reg(0x02938);
870 itv
->yuv_info
.reg_293c
= read_reg(0x0293c);
871 itv
->yuv_info
.reg_2940
= read_reg(0x02940);
872 itv
->yuv_info
.reg_2944
= read_reg(0x02944);
873 itv
->yuv_info
.reg_2948
= read_reg(0x02948);
874 itv
->yuv_info
.reg_294c
= read_reg(0x0294c);
875 itv
->yuv_info
.reg_2950
= read_reg(0x02950);
876 itv
->yuv_info
.reg_2954
= read_reg(0x02954);
877 itv
->yuv_info
.reg_2958
= read_reg(0x02958);
878 itv
->yuv_info
.reg_295c
= read_reg(0x0295c);
879 itv
->yuv_info
.reg_2960
= read_reg(0x02960);
880 itv
->yuv_info
.reg_2964
= read_reg(0x02964);
881 itv
->yuv_info
.reg_2968
= read_reg(0x02968);
882 itv
->yuv_info
.reg_296c
= read_reg(0x0296c);
883 itv
->yuv_info
.reg_2970
= read_reg(0x02970);
885 itv
->yuv_info
.v_filter_1
= -1;
886 itv
->yuv_info
.v_filter_2
= -1;
887 itv
->yuv_info
.h_filter
= -1;
889 /* Set some valid size info */
890 itv
->yuv_info
.osd_x_offset
= read_reg(0x02a04) & 0x00000FFF;
891 itv
->yuv_info
.osd_y_offset
= (read_reg(0x02a04) >> 16) & 0x00000FFF;
893 /* Bit 2 of reg 2878 indicates current decoder output format
895 if (read_reg(0x2878) & 4)
896 itv
->yuv_info
.decode_height
= 576;
898 itv
->yuv_info
.decode_height
= 480;
900 /* If no visible size set, assume full size */
901 if (!itv
->yuv_info
.osd_vis_w
) itv
->yuv_info
.osd_vis_w
= 720 - itv
->yuv_info
.osd_x_offset
;
902 if (!itv
->yuv_info
.osd_vis_h
) itv
->yuv_info
.osd_vis_h
= itv
->yuv_info
.decode_height
- itv
->yuv_info
.osd_y_offset
;
904 /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */
905 itv
->yuv_info
.blanking_ptr
= kzalloc(720*16,GFP_KERNEL
);
906 if (itv
->yuv_info
.blanking_ptr
) {
907 itv
->yuv_info
.blanking_dmaptr
= pci_map_single(itv
->dev
, itv
->yuv_info
.blanking_ptr
, 720*16, PCI_DMA_TODEVICE
);
910 itv
->yuv_info
.blanking_dmaptr
= 0;
911 IVTV_DEBUG_WARN ("Failed to allocate yuv blanking buffer\n");
914 IVTV_DEBUG_WARN("Enable video output\n");
915 write_reg_sync(0x00108080, 0x2898);
917 /* Enable YUV decoder output */
918 write_reg_sync(0x01, IVTV_REG_VDM
);
920 set_bit(IVTV_F_I_DECODING_YUV
, &itv
->i_flags
);
921 atomic_set(&itv
->yuv_info
.next_dma_frame
,0);
924 int ivtv_yuv_prep_frame(struct ivtv
*itv
, struct ivtv_dma_frame
*args
)
929 int frame
, next_fill_frame
, last_fill_frame
;
931 IVTV_DEBUG_INFO("yuv_prep_frame\n");
933 if (atomic_read(&itv
->yuv_info
.next_dma_frame
) == -1) ivtv_yuv_init(itv
);
935 frame
= atomic_read(&itv
->yuv_info
.next_fill_frame
);
936 next_fill_frame
= (frame
+ 1) & 0x3;
937 last_fill_frame
= (atomic_read(&itv
->yuv_info
.next_dma_frame
)+1) & 0x3;
939 if (next_fill_frame
!= last_fill_frame
&& last_fill_frame
!= frame
) {
940 /* Buffers are full - Overwrite the last frame */
941 next_fill_frame
= frame
;
942 frame
= (frame
- 1) & 3;
945 /* Take a snapshot of the yuv coordinate information */
946 itv
->yuv_info
.new_frame_info
[frame
].src_x
= args
->src
.left
;
947 itv
->yuv_info
.new_frame_info
[frame
].src_y
= args
->src
.top
;
948 itv
->yuv_info
.new_frame_info
[frame
].src_w
= args
->src
.width
;
949 itv
->yuv_info
.new_frame_info
[frame
].src_h
= args
->src
.height
;
950 itv
->yuv_info
.new_frame_info
[frame
].dst_x
= args
->dst
.left
;
951 itv
->yuv_info
.new_frame_info
[frame
].dst_y
= args
->dst
.top
;
952 itv
->yuv_info
.new_frame_info
[frame
].dst_w
= args
->dst
.width
;
953 itv
->yuv_info
.new_frame_info
[frame
].dst_h
= args
->dst
.height
;
954 itv
->yuv_info
.new_frame_info
[frame
].tru_x
= args
->dst
.left
;
955 itv
->yuv_info
.new_frame_info
[frame
].tru_w
= args
->src_width
;
956 itv
->yuv_info
.new_frame_info
[frame
].tru_h
= args
->src_height
;
958 /* Are we going to offset the Y plane */
959 if (args
->src
.height
+ args
->src
.top
< 512-16)
960 itv
->yuv_info
.new_frame_info
[frame
].offset_y
= 1;
962 itv
->yuv_info
.new_frame_info
[frame
].offset_y
= 0;
964 /* Snapshot the osd pan info */
965 itv
->yuv_info
.new_frame_info
[frame
].pan_x
= itv
->yuv_info
.osd_x_pan
;
966 itv
->yuv_info
.new_frame_info
[frame
].pan_y
= itv
->yuv_info
.osd_y_pan
;
967 itv
->yuv_info
.new_frame_info
[frame
].vis_w
= itv
->yuv_info
.osd_vis_w
;
968 itv
->yuv_info
.new_frame_info
[frame
].vis_h
= itv
->yuv_info
.osd_vis_h
;
970 itv
->yuv_info
.new_frame_info
[frame
].update
= 0;
971 itv
->yuv_info
.new_frame_info
[frame
].interlaced_y
= 0;
972 itv
->yuv_info
.new_frame_info
[frame
].interlaced_uv
= 0;
974 if (memcmp (&itv
->yuv_info
.old_frame_info_args
, &itv
->yuv_info
.new_frame_info
[frame
],
975 sizeof (itv
->yuv_info
.new_frame_info
[frame
]))) {
976 memcpy(&itv
->yuv_info
.old_frame_info_args
, &itv
->yuv_info
.new_frame_info
[frame
], sizeof (itv
->yuv_info
.old_frame_info_args
));
977 itv
->yuv_info
.new_frame_info
[frame
].update
= 1;
978 /* IVTV_DEBUG_YUV ("Requesting register update for frame %d\n",frame); */
982 mutex_lock(&itv
->udma
.lock
);
984 if ((rc
= ivtv_yuv_prep_user_dma(itv
, &itv
->udma
, args
)) != 0) {
985 mutex_unlock(&itv
->udma
.lock
);
989 ivtv_udma_prepare(itv
);
990 prepare_to_wait(&itv
->dma_waitq
, &wait
, TASK_INTERRUPTIBLE
);
991 /* if no UDMA is pending and no UDMA is in progress, then the DMA
993 while (itv
->i_flags
& (IVTV_F_I_UDMA_PENDING
| IVTV_F_I_UDMA
)) {
994 /* don't interrupt if the DMA is in progress but break off
995 a still pending DMA. */
996 got_sig
= signal_pending(current
);
997 if (got_sig
&& test_and_clear_bit(IVTV_F_I_UDMA_PENDING
, &itv
->i_flags
))
1002 finish_wait(&itv
->dma_waitq
, &wait
);
1004 /* Unmap Last DMA Xfer */
1005 ivtv_udma_unmap(itv
);
1008 IVTV_DEBUG_INFO("User stopped YUV UDMA\n");
1009 mutex_unlock(&itv
->udma
.lock
);
1013 atomic_set(&itv
->yuv_info
.next_fill_frame
, next_fill_frame
);
1015 mutex_unlock(&itv
->udma
.lock
);
1019 void ivtv_yuv_close(struct ivtv
*itv
)
1021 int h_filter
, v_filter_1
, v_filter_2
;
1023 IVTV_DEBUG_YUV("ivtv_yuv_close\n");
1024 ivtv_waitq(&itv
->vsync_waitq
);
1026 atomic_set(&itv
->yuv_info
.next_dma_frame
, -1);
1027 atomic_set(&itv
->yuv_info
.next_fill_frame
, 0);
1029 /* Reset registers we have changed so mpeg playback works */
1031 /* If we fully restore this register, the display may remain active.
1032 Restore, but set one bit to blank the video. Firmware will always
1033 clear this bit when needed, so not a problem. */
1034 write_reg(itv
->yuv_info
.reg_2898
| 0x01000000, 0x2898);
1036 write_reg(itv
->yuv_info
.reg_2834
, 0x02834);
1037 write_reg(itv
->yuv_info
.reg_2838
, 0x02838);
1038 write_reg(itv
->yuv_info
.reg_283c
, 0x0283c);
1039 write_reg(itv
->yuv_info
.reg_2840
, 0x02840);
1040 write_reg(itv
->yuv_info
.reg_2844
, 0x02844);
1041 write_reg(itv
->yuv_info
.reg_2848
, 0x02848);
1042 write_reg(itv
->yuv_info
.reg_2854
, 0x02854);
1043 write_reg(itv
->yuv_info
.reg_285c
, 0x0285c);
1044 write_reg(itv
->yuv_info
.reg_2864
, 0x02864);
1045 write_reg(itv
->yuv_info
.reg_2870
, 0x02870);
1046 write_reg(itv
->yuv_info
.reg_2874
, 0x02874);
1047 write_reg(itv
->yuv_info
.reg_2890
, 0x02890);
1048 write_reg(itv
->yuv_info
.reg_289c
, 0x0289c);
1050 write_reg(itv
->yuv_info
.reg_2918
, 0x02918);
1051 write_reg(itv
->yuv_info
.reg_291c
, 0x0291c);
1052 write_reg(itv
->yuv_info
.reg_2920
, 0x02920);
1053 write_reg(itv
->yuv_info
.reg_2924
, 0x02924);
1054 write_reg(itv
->yuv_info
.reg_2928
, 0x02928);
1055 write_reg(itv
->yuv_info
.reg_292c
, 0x0292c);
1056 write_reg(itv
->yuv_info
.reg_2930
, 0x02930);
1057 write_reg(itv
->yuv_info
.reg_2934
, 0x02934);
1058 write_reg(itv
->yuv_info
.reg_2938
, 0x02938);
1059 write_reg(itv
->yuv_info
.reg_293c
, 0x0293c);
1060 write_reg(itv
->yuv_info
.reg_2940
, 0x02940);
1061 write_reg(itv
->yuv_info
.reg_2944
, 0x02944);
1062 write_reg(itv
->yuv_info
.reg_2948
, 0x02948);
1063 write_reg(itv
->yuv_info
.reg_294c
, 0x0294c);
1064 write_reg(itv
->yuv_info
.reg_2950
, 0x02950);
1065 write_reg(itv
->yuv_info
.reg_2954
, 0x02954);
1066 write_reg(itv
->yuv_info
.reg_2958
, 0x02958);
1067 write_reg(itv
->yuv_info
.reg_295c
, 0x0295c);
1068 write_reg(itv
->yuv_info
.reg_2960
, 0x02960);
1069 write_reg(itv
->yuv_info
.reg_2964
, 0x02964);
1070 write_reg(itv
->yuv_info
.reg_2968
, 0x02968);
1071 write_reg(itv
->yuv_info
.reg_296c
, 0x0296c);
1072 write_reg(itv
->yuv_info
.reg_2970
, 0x02970);
1074 /* Prepare to restore filters */
1076 /* First the horizontal filter */
1077 if ((itv
->yuv_info
.reg_2834
& 0x0000FFFF) == (itv
->yuv_info
.reg_2834
>> 16)) {
1078 /* An exact size match uses filter 0 */
1082 /* Figure out which filter to use */
1083 h_filter
= ((itv
->yuv_info
.reg_2834
<< 16) / (itv
->yuv_info
.reg_2834
>> 16)) >> 15;
1084 h_filter
= (h_filter
>> 1) + (h_filter
& 1);
1085 /* Only an exact size match can use filter 0. */
1086 if (h_filter
< 1) h_filter
= 1;
1089 /* Now the vertical filter */
1090 if ((itv
->yuv_info
.reg_2918
& 0x0000FFFF) == (itv
->yuv_info
.reg_2918
>> 16)) {
1091 /* An exact size match uses filter 0/1 */
1096 /* Figure out which filter to use */
1097 v_filter_1
= ((itv
->yuv_info
.reg_2918
<< 16) / (itv
->yuv_info
.reg_2918
>> 16)) >> 15;
1098 v_filter_1
= (v_filter_1
>> 1) + (v_filter_1
& 1);
1099 /* Only an exact size match can use filter 0 */
1100 if (v_filter_1
== 0) v_filter_1
= 1;
1101 v_filter_2
= v_filter_1
;
1104 /* Now restore the filters */
1105 ivtv_yuv_filter (itv
,h_filter
,v_filter_1
,v_filter_2
);
1107 /* and clear a few registers */
1108 write_reg(0, 0x02814);
1109 write_reg(0, 0x0282c);
1110 write_reg(0, 0x02904);
1111 write_reg(0, 0x02910);
1113 /* Release the blanking buffer */
1114 if (itv
->yuv_info
.blanking_ptr
) {
1115 kfree (itv
->yuv_info
.blanking_ptr
);
1116 itv
->yuv_info
.blanking_ptr
= NULL
;
1117 pci_unmap_single(itv
->dev
, itv
->yuv_info
.blanking_dmaptr
, 720*16, PCI_DMA_TODEVICE
);
1120 /* Invalidate the old dimension information */
1121 itv
->yuv_info
.old_frame_info
.src_w
= 0;
1122 itv
->yuv_info
.old_frame_info
.src_h
= 0;
1123 itv
->yuv_info
.old_frame_info_args
.src_w
= 0;
1124 itv
->yuv_info
.old_frame_info_args
.src_h
= 0;
1127 clear_bit(IVTV_F_I_DECODING_YUV
, &itv
->i_flags
);