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 const u32 yuv_offset[4] = {
26 IVTV_YUV_BUFFER_OFFSET,
27 IVTV_YUV_BUFFER_OFFSET_1,
28 IVTV_YUV_BUFFER_OFFSET_2,
29 IVTV_YUV_BUFFER_OFFSET_3
32 static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
33 struct ivtv_dma_frame *args)
35 struct ivtv_dma_page_info y_dma;
36 struct ivtv_dma_page_info uv_dma;
39 int y_pages, uv_pages;
41 unsigned long y_buffer_offset, uv_buffer_offset;
42 int y_decode_height, uv_decode_height, y_size;
43 int frame = atomic_read(&itv->yuv_info.next_fill_frame);
45 y_buffer_offset = IVTV_DECODER_OFFSET + yuv_offset[frame];
46 uv_buffer_offset = y_buffer_offset + IVTV_YUV_BUFFER_UV_OFFSET;
48 y_decode_height = uv_decode_height = args->src.height + args->src.top;
50 if (y_decode_height < 512-16)
51 y_buffer_offset += 720 * 16;
53 if (y_decode_height & 15)
54 y_decode_height = (y_decode_height + 16) & ~15;
56 if (uv_decode_height & 31)
57 uv_decode_height = (uv_decode_height + 32) & ~31;
59 y_size = 720 * y_decode_height;
62 if (dma->SG_length || dma->page_count) {
63 IVTV_DEBUG_WARN("prep_user_dma: SG_length %d page_count %d still full?\n",
64 dma->SG_length, dma->page_count);
68 ivtv_udma_get_page_info (&y_dma, (unsigned long)args->y_source, 720 * y_decode_height);
69 ivtv_udma_get_page_info (&uv_dma, (unsigned long)args->uv_source, 360 * uv_decode_height);
71 /* Get user pages for DMA Xfer */
72 down_read(¤t->mm->mmap_sem);
73 y_pages = get_user_pages(current, current->mm, y_dma.uaddr, y_dma.page_count, 0, 1, &dma->map[0], NULL);
74 uv_pages = get_user_pages(current, current->mm, uv_dma.uaddr, uv_dma.page_count, 0, 1, &dma->map[y_pages], NULL);
75 up_read(¤t->mm->mmap_sem);
77 dma->page_count = y_dma.page_count + uv_dma.page_count;
79 if (y_pages + uv_pages != dma->page_count) {
80 IVTV_DEBUG_WARN("failed to map user pages, returned %d instead of %d\n",
81 y_pages + uv_pages, dma->page_count);
83 for (i = 0; i < dma->page_count; i++) {
84 put_page(dma->map[i]);
90 /* Fill & map SG List */
91 if (ivtv_udma_fill_sg_list (dma, &uv_dma, ivtv_udma_fill_sg_list (dma, &y_dma, 0)) < 0) {
92 IVTV_DEBUG_WARN("could not allocate bounce buffers for highmem userspace buffers\n");
93 for (i = 0; i < dma->page_count; i++) {
94 put_page(dma->map[i]);
99 dma->SG_length = pci_map_sg(itv->dev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE);
101 /* Fill SG Array with new values */
102 ivtv_udma_fill_sg_array (dma, y_buffer_offset, uv_buffer_offset, y_size);
104 /* If we've offset the y plane, ensure top area is blanked */
105 if (args->src.height + args->src.top < 512-16) {
106 if (itv->yuv_info.blanking_dmaptr) {
107 dma->SGarray[dma->SG_length].size = cpu_to_le32(720*16);
108 dma->SGarray[dma->SG_length].src = cpu_to_le32(itv->yuv_info.blanking_dmaptr);
109 dma->SGarray[dma->SG_length].dst = cpu_to_le32(IVTV_DECODER_OFFSET + yuv_offset[frame]);
114 /* Tag SG Array with Interrupt Bit */
115 dma->SGarray[dma->SG_length - 1].size |= cpu_to_le32(0x80000000);
117 ivtv_udma_sync_for_device(itv);
121 /* We rely on a table held in the firmware - Quick check. */
122 int ivtv_yuv_filter_check(struct ivtv *itv)
124 int i, offset_y, offset_uv;
126 for (i=0, offset_y = 16, offset_uv = 4; i<16; i++, offset_y += 24, offset_uv += 12) {
127 if ((read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + offset_y) != i << 16) ||
128 (read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET + offset_uv) != i << 16)) {
129 IVTV_WARN ("YUV filter table not found in firmware.\n");
136 static void ivtv_yuv_filter(struct ivtv *itv, int h_filter, int v_filter_1, int v_filter_2)
138 int filter_index, filter_line;
140 /* If any filter is -1, then don't update it */
142 if (h_filter > 4) h_filter = 4;
143 filter_index = h_filter * 384;
145 while (filter_line < 16) {
146 write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + filter_index), 0x02804);
147 write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + filter_index), 0x0281c);
149 write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + filter_index), 0x02808);
150 write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + filter_index), 0x02820);
152 write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + filter_index), 0x0280c);
153 write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + filter_index), 0x02824);
155 write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + filter_index), 0x02810);
156 write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + filter_index), 0x02828);
158 write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + filter_index), 0x02814);
159 write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + filter_index), 0x0282c);
161 write_reg(0, 0x02818);
162 write_reg(0, 0x02830);
165 IVTV_DEBUG_YUV("h_filter -> %d\n",h_filter);
168 if (v_filter_1 > -1) {
169 if (v_filter_1 > 4) v_filter_1 = 4;
170 filter_index = v_filter_1 * 192;
172 while (filter_line < 16) {
173 write_reg(read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET + filter_index), 0x02900);
175 write_reg(read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET + filter_index), 0x02904);
177 write_reg(0, 0x02908);
180 IVTV_DEBUG_YUV("v_filter_1 -> %d\n",v_filter_1);
183 if (v_filter_2 > -1) {
184 if (v_filter_2 > 4) v_filter_2 = 4;
185 filter_index = v_filter_2 * 192;
187 while (filter_line < 16) {
188 write_reg(read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET + filter_index), 0x0290c);
190 write_reg(read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET + filter_index), 0x02910);
192 write_reg(0, 0x02914);
195 IVTV_DEBUG_YUV("v_filter_2 -> %d\n",v_filter_2);
199 static void ivtv_yuv_handle_horizontal(struct ivtv *itv, struct yuv_frame_info *window)
201 u32 reg_2834, reg_2838, reg_283c;
202 u32 reg_2844, reg_2854, reg_285c;
203 u32 reg_2864, reg_2874, reg_2890;
204 u32 reg_2870, reg_2870_base, reg_2870_offset;
209 IVTV_DEBUG_WARN( "Need to adjust to width %d src_w %d dst_w %d src_x %d dst_x %d\n",
210 window->tru_w, window->src_w, window->dst_w,window->src_x, window->dst_x);
212 /* How wide is the src image */
213 x_cutoff = window->src_w + window->src_x;
215 /* Set the display width */
216 reg_2834 = window->dst_w;
219 /* Set the display position */
220 reg_2890 = window->dst_x;
222 /* Index into the image horizontally */
225 /* 2870 is normally fudged to align video coords with osd coords.
226 If running full screen, it causes an unwanted left shift
227 Remove the fudge if we almost fill the screen.
228 Gradually adjust the offset to avoid the video 'snapping'
229 left/right if it gets dragged through this region.
230 Only do this if osd is full width. */
231 if (window->vis_w == 720) {
232 if ((window->tru_x - window->pan_x > -1) && (window->tru_x - window->pan_x <= 40) && (window->dst_w >= 680)){
233 reg_2870 = 10 - (window->tru_x - window->pan_x) / 4;
235 else if ((window->tru_x - window->pan_x < 0) && (window->tru_x - window->pan_x >= -20) && (window->dst_w >= 660)) {
236 reg_2870 = (10 + (window->tru_x - window->pan_x) / 2);
239 if (window->dst_w >= window->src_w)
240 reg_2870 = reg_2870 << 16 | reg_2870;
242 reg_2870 = ((reg_2870 & ~1) << 15) | (reg_2870 & ~1);
245 if (window->dst_w < window->src_w)
246 reg_2870 = 0x000d000e - reg_2870;
248 reg_2870 = 0x0012000e - reg_2870;
250 /* We're also using 2870 to shift the image left (src_x & negative dst_x) */
251 reg_2870_offset = (window->src_x*((window->dst_w << 21)/window->src_w))>>19;
253 if (window->dst_w >= window->src_w) {
255 master_width = (window->src_w * 0x00200000) / (window->dst_w);
256 if (master_width * window->dst_w != window->src_w * 0x00200000) master_width ++;
257 reg_2834 = (reg_2834 << 16) | x_cutoff;
258 reg_2838 = (reg_2838 << 16) | x_cutoff;
259 reg_283c = master_width >> 2;
260 reg_2844 = master_width >> 2;
261 reg_2854 = master_width;
262 reg_285c = master_width >> 1;
263 reg_2864 = master_width >> 1;
265 /* We also need to factor in the scaling
266 (src_w - dst_w) / (src_w / 4) */
267 if (window->dst_w > window->src_w)
268 reg_2870_base = ((window->dst_w - window->src_w)<<16) / (window->src_w <<14);
272 reg_2870 += (((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 2) + (reg_2870_base << 17 | reg_2870_base);
275 else if (window->dst_w < window->src_w / 2) {
276 master_width = (window->src_w * 0x00080000) / window->dst_w;
277 if (master_width * window->dst_w != window->src_w * 0x00080000) master_width ++;
278 reg_2834 = (reg_2834 << 16) | x_cutoff;
279 reg_2838 = (reg_2838 << 16) | x_cutoff;
280 reg_283c = master_width >> 2;
281 reg_2844 = master_width >> 1;
282 reg_2854 = master_width;
283 reg_285c = master_width >> 1;
284 reg_2864 = master_width >> 1;
285 reg_2870 += (((reg_2870_offset << 15) & 0xFFFF0000) | reg_2870_offset);
286 reg_2870 += (5 - (((window->src_w + window->src_w / 2) - 1) / window->dst_w)) << 16;
287 reg_2874 = 0x00000012;
290 master_width = (window->src_w * 0x00100000) / window->dst_w;
291 if (master_width * window->dst_w != window->src_w * 0x00100000) master_width ++;
292 reg_2834 = (reg_2834 << 16) | x_cutoff;
293 reg_2838 = (reg_2838 << 16) | x_cutoff;
294 reg_283c = master_width >> 2;
295 reg_2844 = master_width >> 1;
296 reg_2854 = master_width;
297 reg_285c = master_width >> 1;
298 reg_2864 = master_width >> 1;
299 reg_2870 += (((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 1);
300 reg_2870 += (5 - (((window->src_w * 3) - 1) / window->dst_w)) << 16;
301 reg_2874 = 0x00000001;
304 /* Select the horizontal filter */
305 if (window->src_w == window->dst_w) {
306 /* An exact size match uses filter 0 */
310 /* Figure out which filter to use */
311 h_filter = ((window->src_w << 16) / window->dst_w) >> 15;
312 h_filter = (h_filter >> 1) + (h_filter & 1);
313 /* Only an exact size match can use filter 0 */
314 if (h_filter == 0) h_filter = 1;
317 write_reg(reg_2834, 0x02834);
318 write_reg(reg_2838, 0x02838);
319 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);
321 write_reg(reg_283c, 0x0283c);
322 write_reg(reg_2844, 0x02844);
324 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);
326 write_reg(0x00080514, 0x02840);
327 write_reg(0x00100514, 0x02848);
328 IVTV_DEBUG_YUV("Update reg 0x2840 %08x->%08x 0x2848 %08x->%08x\n",itv->yuv_info.reg_2840, 0x00080514, itv->yuv_info.reg_2848, 0x00100514);
330 write_reg(reg_2854, 0x02854);
331 IVTV_DEBUG_YUV("Update reg 0x2854 %08x->%08x \n",itv->yuv_info.reg_2854, reg_2854);
333 write_reg(reg_285c, 0x0285c);
334 write_reg(reg_2864, 0x02864);
335 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);
337 write_reg(reg_2874, 0x02874);
338 IVTV_DEBUG_YUV("Update reg 0x2874 %08x->%08x\n",itv->yuv_info.reg_2874, reg_2874);
340 write_reg(reg_2870, 0x02870);
341 IVTV_DEBUG_YUV("Update reg 0x2870 %08x->%08x\n",itv->yuv_info.reg_2870, reg_2870);
343 write_reg( reg_2890,0x02890);
344 IVTV_DEBUG_YUV("Update reg 0x2890 %08x->%08x\n",itv->yuv_info.reg_2890, reg_2890);
346 /* Only update the filter if we really need to */
347 if (h_filter != itv->yuv_info.h_filter) {
348 ivtv_yuv_filter (itv,h_filter,-1,-1);
349 itv->yuv_info.h_filter = h_filter;
353 static void ivtv_yuv_handle_vertical(struct ivtv *itv, struct yuv_frame_info *window)
356 u32 reg_2918, reg_291c, reg_2920, reg_2928;
357 u32 reg_2930, reg_2934, reg_293c;
358 u32 reg_2940, reg_2944, reg_294c;
359 u32 reg_2950, reg_2954, reg_2958, reg_295c;
360 u32 reg_2960, reg_2964, reg_2968, reg_296c;
362 u32 src_y_major_y, src_y_minor_y;
363 u32 src_y_major_uv, src_y_minor_uv;
364 u32 reg_2964_base, reg_2968_base;
365 int v_filter_1, v_filter_2;
367 IVTV_DEBUG_WARN("Need to adjust to height %d src_h %d dst_h %d src_y %d dst_y %d\n",
368 window->tru_h, window->src_h, window->dst_h,window->src_y, window->dst_y);
370 /* What scaling mode is being used... */
371 if (window->interlaced_y) {
372 IVTV_DEBUG_YUV("Scaling mode Y: Interlaced\n");
375 IVTV_DEBUG_YUV("Scaling mode Y: Progressive\n");
378 if (window->interlaced_uv) {
379 IVTV_DEBUG_YUV("Scaling mode UV: Interlaced\n");
382 IVTV_DEBUG_YUV("Scaling mode UV: Progressive\n");
385 /* What is the source video being treated as... */
386 if (itv->yuv_info.frame_interlaced) {
387 IVTV_DEBUG_WARN("Source video: Interlaced\n");
390 IVTV_DEBUG_WARN("Source video: Non-interlaced\n");
393 /* We offset into the image using two different index methods, so split
394 the y source coord into two parts. */
395 if (window->src_y < 8) {
396 src_y_minor_uv = window->src_y;
401 src_y_major_uv = window->src_y - 8;
404 src_y_minor_y = src_y_minor_uv;
405 src_y_major_y = src_y_major_uv;
407 if (window->offset_y) src_y_minor_y += 16;
409 if (window->interlaced_y)
410 reg_2918 = (window->dst_h << 16) | (window->src_h + src_y_minor_y);
412 reg_2918 = (window->dst_h << 16) | ((window->src_h + src_y_minor_y) << 1);
414 if (window->interlaced_uv)
415 reg_291c = (window->dst_h << 16) | ((window->src_h + src_y_minor_uv) >> 1);
417 reg_291c = (window->dst_h << 16) | (window->src_h + src_y_minor_uv);
419 reg_2964_base = (src_y_minor_y * ((window->dst_h << 16)/window->src_h)) >> 14;
420 reg_2968_base = (src_y_minor_uv * ((window->dst_h << 16)/window->src_h)) >> 14;
422 if (window->dst_h / 2 >= window->src_h && !window->interlaced_y) {
423 master_height = (window->src_h * 0x00400000) / window->dst_h;
424 if ((window->src_h * 0x00400000) - (master_height * window->dst_h) >= window->dst_h / 2) master_height ++;
425 reg_2920 = master_height >> 2;
426 reg_2928 = master_height >> 3;
427 reg_2930 = master_height;
428 reg_2940 = master_height >> 1;
431 reg_296c = 0x00000000;
433 else if (window->dst_h >= window->src_h) {
434 master_height = (window->src_h * 0x00400000) / window->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 (window->interlaced_y) {
448 if (window->interlaced_uv) reg_2928 >>= 1;
451 else if (window->dst_h >= window->src_h / 2) {
452 master_height = (window->src_h * 0x00200000) / window->dst_h;
453 master_height = (master_height >> 1) + (master_height & 1);
454 reg_2920 = master_height >> 2;
455 reg_2928 = master_height >> 2;
456 reg_2930 = master_height;
457 reg_2940 = master_height;
458 reg_296c = 0x00000101;
459 if (window->interlaced_y) {
466 if (window->interlaced_uv) reg_2928 >>= 1;
470 master_height = (window->src_h * 0x00100000) / window->dst_h;
471 master_height = (master_height >> 1) + (master_height & 1);
472 reg_2920 = master_height >> 2;
473 reg_2928 = master_height >> 2;
474 reg_2930 = master_height;
475 reg_2940 = master_height;
478 reg_296c = 0x00000102;
481 /* FIXME These registers change depending on scaled / unscaled output
482 We really need to work out what they should be */
483 if (window->src_h == window->dst_h){
484 reg_2934 = 0x00020000;
485 reg_293c = 0x00100000;
486 reg_2944 = 0x00040000;
487 reg_294c = 0x000b0000;
490 reg_2934 = 0x00000FF0;
491 reg_293c = 0x00000FF0;
492 reg_2944 = 0x00000FF0;
493 reg_294c = 0x00000FF0;
496 /* The first line to be displayed */
497 reg_2950 = 0x00010000 + src_y_major_y;
498 if (window->interlaced_y) reg_2950 += 0x00010000;
499 reg_2954 = reg_2950 + 1;
501 reg_2958 = 0x00010000 + (src_y_major_y >> 1);
502 if (window->interlaced_uv) reg_2958 += 0x00010000;
503 reg_295c = reg_2958 + 1;
505 if (itv->yuv_info.decode_height == 480)
506 reg_289c = 0x011e0017;
508 reg_289c = 0x01500017;
510 if (window->dst_y < 0)
511 reg_289c = (reg_289c - ((window->dst_y & ~1)<<15))-(window->dst_y >>1);
513 reg_289c = (reg_289c + ((window->dst_y & ~1)<<15))+(window->dst_y >>1);
515 /* How much of the source to decode.
516 Take into account the source offset */
517 reg_2960 = ((src_y_minor_y + window->src_h + src_y_major_y) - 1 ) |
518 ((((src_y_minor_uv + window->src_h + src_y_major_uv) - 1) & ~1) << 15);
520 /* Calculate correct value for register 2964 */
521 if (window->src_h == window->dst_h)
524 reg_2964 = 2 + ((window->dst_h << 1) / window->src_h);
525 reg_2964 = (reg_2964 >> 1) + (reg_2964 & 1);
527 reg_2968 = (reg_2964 << 16) + reg_2964 + (reg_2964 >> 1);
528 reg_2964 = (reg_2964 << 16) + reg_2964 + (reg_2964 * 46 / 94);
530 /* Okay, we've wasted time working out the correct value,
531 but if we use it, it fouls the the window alignment.
532 Fudge it to what we want... */
533 reg_2964 = 0x00010001 + ((reg_2964 & 0x0000FFFF) - (reg_2964 >> 16));
534 reg_2968 = 0x00010001 + ((reg_2968 & 0x0000FFFF) - (reg_2968 >> 16));
536 /* Deviate further from what it should be. I find the flicker headache
537 inducing so try to reduce it slightly. Leave 2968 as-is otherwise
539 if ((reg_2964 != 0x00010001) && (window->dst_h / 2 <= window->src_h))
540 reg_2964 = (reg_2964 & 0xFFFF0000) + ((reg_2964 & 0x0000FFFF)/2);
542 if (!window->interlaced_y) reg_2964 -= 0x00010001;
543 if (!window->interlaced_uv) reg_2968 -= 0x00010001;
545 reg_2964 += ((reg_2964_base << 16) | reg_2964_base);
546 reg_2968 += ((reg_2968_base << 16) | reg_2968_base);
548 /* Select the vertical filter */
549 if (window->src_h == window->dst_h) {
550 /* An exact size match uses filter 0/1 */
555 /* Figure out which filter to use */
556 v_filter_1 = ((window->src_h << 16) / window->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 if (v_filter_1 == 0) v_filter_1 = 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",itv->yuv_info.reg_2934, reg_2934, itv->yuv_info.reg_293c, reg_293c);
566 write_reg(reg_2944, 0x02944);
567 write_reg(reg_294c, 0x0294c);
568 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);
570 /* Ensure 2970 is 0 (does it ever change ?) */
571 /* write_reg(0,0x02970); */
572 /* IVTV_DEBUG_YUV("Update reg 0x2970 %08x->%08x\n",itv->yuv_info.reg_2970, 0); */
574 write_reg(reg_2930, 0x02938);
575 write_reg(reg_2930, 0x02930);
576 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);
578 write_reg(reg_2928, 0x02928);
579 write_reg(reg_2928+0x514, 0x0292C);
580 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);
582 write_reg(reg_2920, 0x02920);
583 write_reg(reg_2920+0x514, 0x02924);
584 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);
586 write_reg (reg_2918,0x02918);
587 write_reg (reg_291c,0x0291C);
588 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);
590 write_reg(reg_296c, 0x0296c);
591 IVTV_DEBUG_YUV("Update reg 0x296c %08x->%08x\n",itv->yuv_info.reg_296c, reg_296c);
593 write_reg(reg_2940, 0x02948);
594 write_reg(reg_2940, 0x02940);
595 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);
597 write_reg(reg_2950, 0x02950);
598 write_reg(reg_2954, 0x02954);
599 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);
601 write_reg(reg_2958, 0x02958);
602 write_reg(reg_295c, 0x0295C);
603 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);
605 write_reg(reg_2960, 0x02960);
606 IVTV_DEBUG_YUV("Update reg 0x2960 %08x->%08x \n",itv->yuv_info.reg_2960, reg_2960);
608 write_reg(reg_2964, 0x02964);
609 write_reg(reg_2968, 0x02968);
610 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);
612 write_reg( reg_289c,0x0289c);
613 IVTV_DEBUG_YUV("Update reg 0x289c %08x->%08x\n",itv->yuv_info.reg_289c, reg_289c);
615 /* Only update filter 1 if we really need to */
616 if (v_filter_1 != itv->yuv_info.v_filter_1) {
617 ivtv_yuv_filter (itv,-1,v_filter_1,-1);
618 itv->yuv_info.v_filter_1 = v_filter_1;
621 /* Only update filter 2 if we really need to */
622 if (v_filter_2 != itv->yuv_info.v_filter_2) {
623 ivtv_yuv_filter (itv,-1,-1,v_filter_2);
624 itv->yuv_info.v_filter_2 = v_filter_2;
629 /* Modify the supplied coordinate information to fit the visible osd area */
630 static u32 ivtv_yuv_window_setup (struct ivtv *itv, struct yuv_frame_info *window)
632 int osd_crop, lace_threshold;
636 lace_threshold = itv->yuv_info.lace_threshold;
637 if (lace_threshold < 0)
638 lace_threshold = itv->yuv_info.decode_height - 1;
640 /* Work out the lace settings */
641 switch (itv->yuv_info.lace_mode) {
642 case IVTV_YUV_MODE_PROGRESSIVE: /* Progressive mode */
643 itv->yuv_info.frame_interlaced = 0;
644 if (window->tru_h < 512 || (window->tru_h > 576 && window->tru_h < 1021))
645 window->interlaced_y = 0;
647 window->interlaced_y = 1;
649 if (window->tru_h < 1021 && (window->dst_h >= window->src_h /2))
650 window->interlaced_uv = 0;
652 window->interlaced_uv = 1;
655 case IVTV_YUV_MODE_AUTO:
656 if (window->tru_h <= lace_threshold || window->tru_h > 576 || window->tru_w > 720){
657 itv->yuv_info.frame_interlaced = 0;
658 if ((window->tru_h < 512) ||
659 (window->tru_h > 576 && window->tru_h < 1021) ||
660 (window->tru_w > 720 && window->tru_h < 1021))
661 window->interlaced_y = 0;
663 window->interlaced_y = 1;
665 if (window->tru_h < 1021 && (window->dst_h >= window->src_h /2))
666 window->interlaced_uv = 0;
668 window->interlaced_uv = 1;
671 itv->yuv_info.frame_interlaced = 1;
672 window->interlaced_y = 1;
673 window->interlaced_uv = 1;
677 case IVTV_YUV_MODE_INTERLACED: /* Interlace mode */
679 itv->yuv_info.frame_interlaced = 1;
680 window->interlaced_y = 1;
681 window->interlaced_uv = 1;
685 /* Sorry, but no negative coords for src */
686 if (window->src_x < 0) window->src_x = 0;
687 if (window->src_y < 0) window->src_y = 0;
689 /* Can only reduce width down to 1/4 original size */
690 if ((osd_crop = window->src_w - ( 4 * window->dst_w )) > 0) {
691 window->src_x += osd_crop / 2;
692 window->src_w = (window->src_w - osd_crop) & ~3;
693 window->dst_w = window->src_w / 4;
694 window->dst_w += window->dst_w & 1;
697 /* Can only reduce height down to 1/4 original size */
698 if (window->src_h / window->dst_h >= 2) {
699 /* Overflow may be because we're running progressive, so force mode switch */
700 window->interlaced_y = 1;
701 /* Make sure we're still within limits for interlace */
702 if ((osd_crop = window->src_h - ( 4 * window->dst_h )) > 0) {
703 /* If we reach here we'll have to force the height. */
704 window->src_y += osd_crop / 2;
705 window->src_h = (window->src_h - osd_crop) & ~3;
706 window->dst_h = window->src_h / 4;
707 window->dst_h += window->dst_h & 1;
711 /* If there's nothing to safe to display, we may as well stop now */
712 if ((int)window->dst_w <= 2 || (int)window->dst_h <= 2 || (int)window->src_w <= 2 || (int)window->src_h <= 2) {
716 /* Ensure video remains inside OSD area */
717 osd_scale = (window->src_h << 16) / window->dst_h;
719 if ((osd_crop = window->pan_y - window->dst_y) > 0) {
720 /* Falls off the upper edge - crop */
721 window->src_y += (osd_scale * osd_crop) >> 16;
722 window->src_h -= (osd_scale * osd_crop) >> 16;
723 window->dst_h -= osd_crop;
727 window->dst_y -= window->pan_y;
730 if ((osd_crop = window->dst_h + window->dst_y - window->vis_h) > 0) {
731 /* Falls off the lower edge - crop */
732 window->dst_h -= osd_crop;
733 window->src_h -= (osd_scale * osd_crop) >> 16;
736 osd_scale = (window->src_w << 16) / window->dst_w;
738 if ((osd_crop = window->pan_x - window->dst_x) > 0) {
739 /* Fall off the left edge - crop */
740 window->src_x += (osd_scale * osd_crop) >> 16;
741 window->src_w -= (osd_scale * osd_crop) >> 16;
742 window->dst_w -= osd_crop;
746 window->dst_x -= window->pan_x;
749 if ((osd_crop = window->dst_w + window->dst_x - window->vis_w) > 0) {
750 /* Falls off the right edge - crop */
751 window->dst_w -= osd_crop;
752 window->src_w -= (osd_scale * osd_crop) >> 16;
755 /* The OSD can be moved. Track to it */
756 window->dst_x += itv->yuv_info.osd_x_offset;
757 window->dst_y += itv->yuv_info.osd_y_offset;
759 /* Width & height for both src & dst must be even.
760 Same for coordinates. */
764 window->src_w += window->src_x & 1;
773 window->src_h += window->src_y & 1;
779 /* Due to rounding, we may have reduced the output size to <1/4 of the source
780 Check again, but this time just resize. Don't change source coordinates */
781 if (window->dst_w < window->src_w / 4) {
783 window->dst_w = window->src_w / 4;
784 window->dst_w += window->dst_w & 1;
786 if (window->dst_h < window->src_h / 4) {
788 window->dst_h = window->src_h / 4;
789 window->dst_h += window->dst_h & 1;
792 /* Check again. If there's nothing to safe to display, stop now */
793 if ((int)window->dst_w <= 2 || (int)window->dst_h <= 2 || (int)window->src_w <= 2 || (int)window->src_h <= 2) {
797 /* Both x offset & width are linked, so they have to be done together */
798 if ((itv->yuv_info.old_frame_info.dst_w != window->dst_w) ||
799 (itv->yuv_info.old_frame_info.src_w != window->src_w) ||
800 (itv->yuv_info.old_frame_info.dst_x != window->dst_x) ||
801 (itv->yuv_info.old_frame_info.src_x != window->src_x) ||
802 (itv->yuv_info.old_frame_info.pan_x != window->pan_x) ||
803 (itv->yuv_info.old_frame_info.vis_w != window->vis_w)) {
804 yuv_update |= IVTV_YUV_UPDATE_HORIZONTAL;
807 if ((itv->yuv_info.old_frame_info.src_h != window->src_h) ||
808 (itv->yuv_info.old_frame_info.dst_h != window->dst_h) ||
809 (itv->yuv_info.old_frame_info.dst_y != window->dst_y) ||
810 (itv->yuv_info.old_frame_info.src_y != window->src_y) ||
811 (itv->yuv_info.old_frame_info.pan_y != window->pan_y) ||
812 (itv->yuv_info.old_frame_info.vis_h != window->vis_h) ||
813 (itv->yuv_info.old_frame_info.lace_mode != window->lace_mode) ||
814 (itv->yuv_info.old_frame_info.interlaced_y != window->interlaced_y) ||
815 (itv->yuv_info.old_frame_info.interlaced_uv != window->interlaced_uv)) {
816 yuv_update |= IVTV_YUV_UPDATE_VERTICAL;
822 /* Update the scaling register to the requested value */
823 void ivtv_yuv_work_handler (struct ivtv *itv)
825 struct yuv_frame_info window;
828 int frame = itv->yuv_info.update_frame;
830 /* IVTV_DEBUG_YUV("Update yuv registers for frame %d\n",frame); */
831 memcpy(&window, &itv->yuv_info.new_frame_info[frame], sizeof (window));
833 /* Update the osd pan info */
834 window.pan_x = itv->yuv_info.osd_x_pan;
835 window.pan_y = itv->yuv_info.osd_y_pan;
836 window.vis_w = itv->yuv_info.osd_vis_w;
837 window.vis_h = itv->yuv_info.osd_vis_h;
839 /* Calculate the display window coordinates. Exit if nothing left */
840 if (!(yuv_update = ivtv_yuv_window_setup (itv, &window)))
843 /* Update horizontal settings */
844 if (yuv_update & IVTV_YUV_UPDATE_HORIZONTAL)
845 ivtv_yuv_handle_horizontal(itv, &window);
847 if (yuv_update & IVTV_YUV_UPDATE_VERTICAL)
848 ivtv_yuv_handle_vertical(itv, &window);
850 memcpy(&itv->yuv_info.old_frame_info, &window, sizeof (itv->yuv_info.old_frame_info));
853 static void ivtv_yuv_init (struct ivtv *itv)
855 IVTV_DEBUG_YUV("ivtv_yuv_init\n");
857 /* Take a snapshot of the current register settings */
858 itv->yuv_info.reg_2834 = read_reg(0x02834);
859 itv->yuv_info.reg_2838 = read_reg(0x02838);
860 itv->yuv_info.reg_283c = read_reg(0x0283c);
861 itv->yuv_info.reg_2840 = read_reg(0x02840);
862 itv->yuv_info.reg_2844 = read_reg(0x02844);
863 itv->yuv_info.reg_2848 = read_reg(0x02848);
864 itv->yuv_info.reg_2854 = read_reg(0x02854);
865 itv->yuv_info.reg_285c = read_reg(0x0285c);
866 itv->yuv_info.reg_2864 = read_reg(0x02864);
867 itv->yuv_info.reg_2870 = read_reg(0x02870);
868 itv->yuv_info.reg_2874 = read_reg(0x02874);
869 itv->yuv_info.reg_2898 = read_reg(0x02898);
870 itv->yuv_info.reg_2890 = read_reg(0x02890);
872 itv->yuv_info.reg_289c = read_reg(0x0289c);
873 itv->yuv_info.reg_2918 = read_reg(0x02918);
874 itv->yuv_info.reg_291c = read_reg(0x0291c);
875 itv->yuv_info.reg_2920 = read_reg(0x02920);
876 itv->yuv_info.reg_2924 = read_reg(0x02924);
877 itv->yuv_info.reg_2928 = read_reg(0x02928);
878 itv->yuv_info.reg_292c = read_reg(0x0292c);
879 itv->yuv_info.reg_2930 = read_reg(0x02930);
880 itv->yuv_info.reg_2934 = read_reg(0x02934);
881 itv->yuv_info.reg_2938 = read_reg(0x02938);
882 itv->yuv_info.reg_293c = read_reg(0x0293c);
883 itv->yuv_info.reg_2940 = read_reg(0x02940);
884 itv->yuv_info.reg_2944 = read_reg(0x02944);
885 itv->yuv_info.reg_2948 = read_reg(0x02948);
886 itv->yuv_info.reg_294c = read_reg(0x0294c);
887 itv->yuv_info.reg_2950 = read_reg(0x02950);
888 itv->yuv_info.reg_2954 = read_reg(0x02954);
889 itv->yuv_info.reg_2958 = read_reg(0x02958);
890 itv->yuv_info.reg_295c = read_reg(0x0295c);
891 itv->yuv_info.reg_2960 = read_reg(0x02960);
892 itv->yuv_info.reg_2964 = read_reg(0x02964);
893 itv->yuv_info.reg_2968 = read_reg(0x02968);
894 itv->yuv_info.reg_296c = read_reg(0x0296c);
895 itv->yuv_info.reg_2970 = read_reg(0x02970);
897 itv->yuv_info.v_filter_1 = -1;
898 itv->yuv_info.v_filter_2 = -1;
899 itv->yuv_info.h_filter = -1;
901 /* Set some valid size info */
902 itv->yuv_info.osd_x_offset = read_reg(0x02a04) & 0x00000FFF;
903 itv->yuv_info.osd_y_offset = (read_reg(0x02a04) >> 16) & 0x00000FFF;
905 /* Bit 2 of reg 2878 indicates current decoder output format
907 if (read_reg(0x2878) & 4)
908 itv->yuv_info.decode_height = 576;
910 itv->yuv_info.decode_height = 480;
912 /* If no visible size set, assume full size */
913 if (!itv->yuv_info.osd_vis_w)
914 itv->yuv_info.osd_vis_w = 720 - itv->yuv_info.osd_x_offset;
916 if (!itv->yuv_info.osd_vis_h) {
917 itv->yuv_info.osd_vis_h = itv->yuv_info.decode_height - itv->yuv_info.osd_y_offset;
919 /* If output video standard has changed, requested height may
921 if (itv->yuv_info.osd_vis_h + itv->yuv_info.osd_y_offset > itv->yuv_info.decode_height) {
922 IVTV_DEBUG_WARN("Clipping yuv output - fb size (%d) exceeds video standard limit (%d)\n",
923 itv->yuv_info.osd_vis_h + itv->yuv_info.osd_y_offset,
924 itv->yuv_info.decode_height);
925 itv->yuv_info.osd_vis_h = itv->yuv_info.decode_height - itv->yuv_info.osd_y_offset;
929 /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */
930 itv->yuv_info.blanking_ptr = kzalloc(720*16,GFP_KERNEL);
931 if (itv->yuv_info.blanking_ptr) {
932 itv->yuv_info.blanking_dmaptr = pci_map_single(itv->dev, itv->yuv_info.blanking_ptr, 720*16, PCI_DMA_TODEVICE);
935 itv->yuv_info.blanking_dmaptr = 0;
936 IVTV_DEBUG_WARN ("Failed to allocate yuv blanking buffer\n");
939 IVTV_DEBUG_WARN("Enable video output\n");
940 write_reg_sync(0x00108080, 0x2898);
942 /* Enable YUV decoder output */
943 write_reg_sync(0x01, IVTV_REG_VDM);
945 set_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
946 atomic_set(&itv->yuv_info.next_dma_frame,0);
949 int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
954 int frame, next_fill_frame, last_fill_frame;
955 int register_update = 0;
957 IVTV_DEBUG_INFO("yuv_prep_frame\n");
959 if (atomic_read(&itv->yuv_info.next_dma_frame) == -1) ivtv_yuv_init(itv);
961 frame = atomic_read(&itv->yuv_info.next_fill_frame);
962 next_fill_frame = (frame + 1) & 0x3;
963 last_fill_frame = (atomic_read(&itv->yuv_info.next_dma_frame)+1) & 0x3;
965 if (next_fill_frame != last_fill_frame && last_fill_frame != frame) {
966 /* Buffers are full - Overwrite the last frame */
967 next_fill_frame = frame;
968 frame = (frame - 1) & 3;
969 register_update = itv->yuv_info.new_frame_info[frame].update;
972 /* Take a snapshot of the yuv coordinate information */
973 itv->yuv_info.new_frame_info[frame].src_x = args->src.left;
974 itv->yuv_info.new_frame_info[frame].src_y = args->src.top;
975 itv->yuv_info.new_frame_info[frame].src_w = args->src.width;
976 itv->yuv_info.new_frame_info[frame].src_h = args->src.height;
977 itv->yuv_info.new_frame_info[frame].dst_x = args->dst.left;
978 itv->yuv_info.new_frame_info[frame].dst_y = args->dst.top;
979 itv->yuv_info.new_frame_info[frame].dst_w = args->dst.width;
980 itv->yuv_info.new_frame_info[frame].dst_h = args->dst.height;
981 itv->yuv_info.new_frame_info[frame].tru_x = args->dst.left;
982 itv->yuv_info.new_frame_info[frame].tru_w = args->src_width;
983 itv->yuv_info.new_frame_info[frame].tru_h = args->src_height;
985 /* Snapshot field order */
986 itv->yuv_info.sync_field[frame] = itv->yuv_info.lace_sync_field;
988 /* Are we going to offset the Y plane */
989 if (args->src.height + args->src.top < 512-16)
990 itv->yuv_info.new_frame_info[frame].offset_y = 1;
992 itv->yuv_info.new_frame_info[frame].offset_y = 0;
994 /* Snapshot the osd pan info */
995 itv->yuv_info.new_frame_info[frame].pan_x = itv->yuv_info.osd_x_pan;
996 itv->yuv_info.new_frame_info[frame].pan_y = itv->yuv_info.osd_y_pan;
997 itv->yuv_info.new_frame_info[frame].vis_w = itv->yuv_info.osd_vis_w;
998 itv->yuv_info.new_frame_info[frame].vis_h = itv->yuv_info.osd_vis_h;
1000 itv->yuv_info.new_frame_info[frame].update = 0;
1001 itv->yuv_info.new_frame_info[frame].interlaced_y = 0;
1002 itv->yuv_info.new_frame_info[frame].interlaced_uv = 0;
1003 itv->yuv_info.new_frame_info[frame].lace_mode = itv->yuv_info.lace_mode;
1005 if (memcmp (&itv->yuv_info.old_frame_info_args, &itv->yuv_info.new_frame_info[frame],
1006 sizeof (itv->yuv_info.new_frame_info[frame]))) {
1007 memcpy(&itv->yuv_info.old_frame_info_args, &itv->yuv_info.new_frame_info[frame], sizeof (itv->yuv_info.old_frame_info_args));
1008 itv->yuv_info.new_frame_info[frame].update = 1;
1009 /* IVTV_DEBUG_YUV ("Requesting register update for frame %d\n",frame); */
1012 itv->yuv_info.new_frame_info[frame].update |= register_update;
1014 /* Should this frame be delayed ? */
1015 if (itv->yuv_info.sync_field[frame] != itv->yuv_info.sync_field[(frame - 1) & 3])
1016 itv->yuv_info.field_delay[frame] = 1;
1018 itv->yuv_info.field_delay[frame] = 0;
1021 mutex_lock(&itv->udma.lock);
1023 if ((rc = ivtv_yuv_prep_user_dma(itv, &itv->udma, args)) != 0) {
1024 mutex_unlock(&itv->udma.lock);
1028 ivtv_udma_prepare(itv);
1029 prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
1030 /* if no UDMA is pending and no UDMA is in progress, then the DMA
1032 while (itv->i_flags & (IVTV_F_I_UDMA_PENDING | IVTV_F_I_UDMA)) {
1033 /* don't interrupt if the DMA is in progress but break off
1034 a still pending DMA. */
1035 got_sig = signal_pending(current);
1036 if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags))
1041 finish_wait(&itv->dma_waitq, &wait);
1043 /* Unmap Last DMA Xfer */
1044 ivtv_udma_unmap(itv);
1047 IVTV_DEBUG_INFO("User stopped YUV UDMA\n");
1048 mutex_unlock(&itv->udma.lock);
1052 atomic_set(&itv->yuv_info.next_fill_frame, next_fill_frame);
1054 mutex_unlock(&itv->udma.lock);
1058 void ivtv_yuv_close(struct ivtv *itv)
1060 int h_filter, v_filter_1, v_filter_2;
1062 IVTV_DEBUG_YUV("ivtv_yuv_close\n");
1063 ivtv_waitq(&itv->vsync_waitq);
1065 atomic_set(&itv->yuv_info.next_dma_frame, -1);
1066 atomic_set(&itv->yuv_info.next_fill_frame, 0);
1068 /* Reset registers we have changed so mpeg playback works */
1070 /* If we fully restore this register, the display may remain active.
1071 Restore, but set one bit to blank the video. Firmware will always
1072 clear this bit when needed, so not a problem. */
1073 write_reg(itv->yuv_info.reg_2898 | 0x01000000, 0x2898);
1075 write_reg(itv->yuv_info.reg_2834, 0x02834);
1076 write_reg(itv->yuv_info.reg_2838, 0x02838);
1077 write_reg(itv->yuv_info.reg_283c, 0x0283c);
1078 write_reg(itv->yuv_info.reg_2840, 0x02840);
1079 write_reg(itv->yuv_info.reg_2844, 0x02844);
1080 write_reg(itv->yuv_info.reg_2848, 0x02848);
1081 write_reg(itv->yuv_info.reg_2854, 0x02854);
1082 write_reg(itv->yuv_info.reg_285c, 0x0285c);
1083 write_reg(itv->yuv_info.reg_2864, 0x02864);
1084 write_reg(itv->yuv_info.reg_2870, 0x02870);
1085 write_reg(itv->yuv_info.reg_2874, 0x02874);
1086 write_reg(itv->yuv_info.reg_2890, 0x02890);
1087 write_reg(itv->yuv_info.reg_289c, 0x0289c);
1089 write_reg(itv->yuv_info.reg_2918, 0x02918);
1090 write_reg(itv->yuv_info.reg_291c, 0x0291c);
1091 write_reg(itv->yuv_info.reg_2920, 0x02920);
1092 write_reg(itv->yuv_info.reg_2924, 0x02924);
1093 write_reg(itv->yuv_info.reg_2928, 0x02928);
1094 write_reg(itv->yuv_info.reg_292c, 0x0292c);
1095 write_reg(itv->yuv_info.reg_2930, 0x02930);
1096 write_reg(itv->yuv_info.reg_2934, 0x02934);
1097 write_reg(itv->yuv_info.reg_2938, 0x02938);
1098 write_reg(itv->yuv_info.reg_293c, 0x0293c);
1099 write_reg(itv->yuv_info.reg_2940, 0x02940);
1100 write_reg(itv->yuv_info.reg_2944, 0x02944);
1101 write_reg(itv->yuv_info.reg_2948, 0x02948);
1102 write_reg(itv->yuv_info.reg_294c, 0x0294c);
1103 write_reg(itv->yuv_info.reg_2950, 0x02950);
1104 write_reg(itv->yuv_info.reg_2954, 0x02954);
1105 write_reg(itv->yuv_info.reg_2958, 0x02958);
1106 write_reg(itv->yuv_info.reg_295c, 0x0295c);
1107 write_reg(itv->yuv_info.reg_2960, 0x02960);
1108 write_reg(itv->yuv_info.reg_2964, 0x02964);
1109 write_reg(itv->yuv_info.reg_2968, 0x02968);
1110 write_reg(itv->yuv_info.reg_296c, 0x0296c);
1111 write_reg(itv->yuv_info.reg_2970, 0x02970);
1113 /* Prepare to restore filters */
1115 /* First the horizontal filter */
1116 if ((itv->yuv_info.reg_2834 & 0x0000FFFF) == (itv->yuv_info.reg_2834 >> 16)) {
1117 /* An exact size match uses filter 0 */
1121 /* Figure out which filter to use */
1122 h_filter = ((itv->yuv_info.reg_2834 << 16) / (itv->yuv_info.reg_2834 >> 16)) >> 15;
1123 h_filter = (h_filter >> 1) + (h_filter & 1);
1124 /* Only an exact size match can use filter 0. */
1125 if (h_filter < 1) h_filter = 1;
1128 /* Now the vertical filter */
1129 if ((itv->yuv_info.reg_2918 & 0x0000FFFF) == (itv->yuv_info.reg_2918 >> 16)) {
1130 /* An exact size match uses filter 0/1 */
1135 /* Figure out which filter to use */
1136 v_filter_1 = ((itv->yuv_info.reg_2918 << 16) / (itv->yuv_info.reg_2918 >> 16)) >> 15;
1137 v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1);
1138 /* Only an exact size match can use filter 0 */
1139 if (v_filter_1 == 0) v_filter_1 = 1;
1140 v_filter_2 = v_filter_1;
1143 /* Now restore the filters */
1144 ivtv_yuv_filter (itv,h_filter,v_filter_1,v_filter_2);
1146 /* and clear a few registers */
1147 write_reg(0, 0x02814);
1148 write_reg(0, 0x0282c);
1149 write_reg(0, 0x02904);
1150 write_reg(0, 0x02910);
1152 /* Release the blanking buffer */
1153 if (itv->yuv_info.blanking_ptr) {
1154 kfree (itv->yuv_info.blanking_ptr);
1155 itv->yuv_info.blanking_ptr = NULL;
1156 pci_unmap_single(itv->dev, itv->yuv_info.blanking_dmaptr, 720*16, PCI_DMA_TODEVICE);
1159 /* Invalidate the old dimension information */
1160 itv->yuv_info.old_frame_info.src_w = 0;
1161 itv->yuv_info.old_frame_info.src_h = 0;
1162 itv->yuv_info.old_frame_info_args.src_w = 0;
1163 itv->yuv_info.old_frame_info_args.src_h = 0;
1166 clear_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);