Committer: Michael Beasley <mike@snafu.setup>
[mikesnafu-overlay.git] / drivers / media / video / ivtv / ivtv-yuv.c
blob85183480a2259e610aaad59e4341dd4d91d4d5c4
1 /*
2 yuv support
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"
23 #include "ivtv-yuv.h"
25 /* YUV buffer offsets */
26 const u32 yuv_offset[IVTV_YUV_BUFFERS] = {
27 0x001a8600,
28 0x00240400,
29 0x002d8200,
30 0x00370000,
31 0x00029000,
32 0x000C0E00,
33 0x006B0400,
34 0x00748200
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];
45 int i;
46 int y_pages, uv_pages;
47 unsigned long y_buffer_offset, uv_buffer_offset;
48 int y_decode_height, uv_decode_height, y_size;
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;
55 if (f->offset_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;
66 /* Still in USE */
67 if (dma->SG_length || dma->page_count) {
68 IVTV_DEBUG_WARN
69 ("prep_user_dma: SG_length %d page_count %d still full?\n",
70 dma->SG_length, dma->page_count);
71 return -EBUSY;
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(&current->mm->mmap_sem);
79 y_pages = get_user_pages(current, current->mm, y_dma.uaddr, y_dma.page_count, 0, 1, &dma->map[0], NULL);
80 uv_pages = get_user_pages(current, current->mm, uv_dma.uaddr, uv_dma.page_count, 0, 1, &dma->map[y_pages], NULL);
81 up_read(&current->mm->mmap_sem);
83 dma->page_count = y_dma.page_count + uv_dma.page_count;
85 if (y_pages + uv_pages != dma->page_count) {
86 IVTV_DEBUG_WARN
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]);
93 dma->page_count = 0;
94 return -EINVAL;
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]);
103 dma->page_count = 0;
104 return -ENOMEM;
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]);
116 dma->SG_length++;
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);
123 return 0;
126 /* We rely on a table held in the firmware - Quick check. */
127 int ivtv_yuv_filter_check(struct ivtv *itv)
129 int i, y, uv;
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");
135 return -1;
138 return 0;
141 static void ivtv_yuv_filter(struct ivtv *itv, int h_filter, int v_filter_1, int v_filter_2)
143 u32 i, line;
145 /* If any filter is -1, then don't update it */
146 if (h_filter > -1) {
147 if (h_filter > 4)
148 h_filter = 4;
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);
153 i += 4;
154 write_reg(read_dec(i), 0x02808);
155 write_reg(read_dec(i), 0x02820);
156 i += 4;
157 write_reg(read_dec(i), 0x0280c);
158 write_reg(read_dec(i), 0x02824);
159 i += 4;
160 write_reg(read_dec(i), 0x02810);
161 write_reg(read_dec(i), 0x02828);
162 i += 4;
163 write_reg(read_dec(i), 0x02814);
164 write_reg(read_dec(i), 0x0282c);
165 i += 8;
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) {
173 if (v_filter_1 > 4)
174 v_filter_1 = 4;
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);
178 i += 4;
179 write_reg(read_dec(i), 0x02904);
180 i += 8;
181 write_reg(0, 0x02908);
183 IVTV_DEBUG_YUV("v_filter_1 -> %d\n", v_filter_1);
186 if (v_filter_2 > -1) {
187 if (v_filter_2 > 4)
188 v_filter_2 = 4;
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);
192 i += 4;
193 write_reg(read_dec(i), 0x02910);
194 i += 8;
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;
208 int x_cutoff;
209 int h_filter;
210 u32 master_width;
212 IVTV_DEBUG_WARN
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 */
220 reg_2834 = f->dst_w;
221 reg_2838 = reg_2834;
223 /* Set the display position */
224 reg_2890 = f->dst_x;
226 /* Index into the image horizontally */
227 reg_2870 = 0;
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;
243 else
244 reg_2870 = ((reg_2870 & ~1) << 15) | (reg_2870 & ~1);
247 if (f->dst_w < f->src_w)
248 reg_2870 = 0x000d000e - reg_2870;
249 else
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) {
256 x_cutoff &= ~1;
257 master_width = (f->src_w * 0x00200000) / (f->dst_w);
258 if (master_width * f->dst_w != f->src_w * 0x00200000)
259 master_width++;
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);
272 else
273 reg_2870_base = 0;
275 reg_2870 += (((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 2) + (reg_2870_base << 17 | reg_2870_base);
276 reg_2874 = 0;
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)
280 master_width++;
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;
291 } else {
292 master_width = (f->src_w * 0x00100000) / f->dst_w;
293 if (master_width * f->dst_w != f->src_w * 0x00100000)
294 master_width++;
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 */
310 h_filter = 0;
311 } else {
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;
366 u32 master_height;
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;
372 u32 reg_289c;
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;
378 IVTV_DEBUG_WARN
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. */
395 if (f->src_y < 8) {
396 src_minor_uv = f->src_y;
397 src_major_uv = 0;
398 } else {
399 src_minor_uv = 8;
400 src_major_uv = f->src_y - 8;
403 src_minor_y = src_minor_uv;
404 src_major_y = src_major_uv;
406 if (f->offset_y)
407 src_minor_y += 16;
409 if (f->interlaced_y)
410 reg_2918 = (f->dst_h << 16) | (f->src_h + src_minor_y);
411 else
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);
416 else
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)
425 master_height++;
426 reg_2920 = master_height >> 2;
427 reg_2928 = master_height >> 3;
428 reg_2930 = master_height;
429 reg_2940 = master_height >> 1;
430 reg_2964_base >>= 3;
431 reg_2968_base >>= 3;
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) {
442 reg_2964_base >>= 3;
443 } else {
444 reg_296c++;
445 reg_2964_base >>= 2;
447 if (f->interlaced_uv)
448 reg_2928 >>= 1;
449 reg_2968_base >>= 3;
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) {
459 reg_2964_base >>= 2;
460 } else {
461 reg_296c++;
462 reg_2964_base >>= 1;
464 if (f->interlaced_uv)
465 reg_2928 >>= 1;
466 reg_2968_base >>= 2;
467 } else {
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;
474 reg_2964_base >>= 1;
475 reg_2968_base >>= 2;
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;
486 } else {
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;
495 if (f->interlaced_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;
506 else
507 reg_289c = 0x01500017;
509 if (f->dst_y < 0)
510 reg_289c = (reg_289c - ((f->dst_y & ~1)<<15))-(f->dst_y >>1);
511 else
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) {
521 reg_2964 = 1;
522 } else {
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
537 colours foul. */
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 */
552 v_filter_1 = 0;
553 v_filter_2 = 1;
554 } else {
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;
645 int osd_crop;
646 u32 osd_scale;
647 u32 yuv_update = 0;
649 /* Sorry, but no negative coords for src */
650 if (f->src_x < 0)
651 f->src_x = 0;
652 if (f->src_y < 0)
653 f->src_y = 0;
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 */
667 f->interlaced_y = 1;
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;
692 f->dst_y = 0;
693 } else {
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;
710 f->dst_x = 0;
711 } else {
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. */
727 f->dst_w &= ~1;
728 f->dst_x &= ~1;
730 f->src_w += f->src_x & 1;
731 f->src_x &= ~1;
733 f->src_w &= ~1;
734 f->dst_w &= ~1;
736 f->dst_h &= ~1;
737 f->dst_y &= ~1;
739 f->src_h += f->src_y & 1;
740 f->src_y &= ~1;
742 f->src_h &= ~1;
743 f->dst_h &= ~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) {
749 f->src_w &= ~3;
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) {
754 f->src_h &= ~3;
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;
781 return yuv_update;
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;
790 u32 yuv_update;
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)))
803 return;
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);
865 yi->v_filter_1 = -1;
866 yi->v_filter_2 = -1;
867 yi->h_filter = -1;
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
874 0 : NTSC 1 : PAL */
875 if (read_reg(0x2878) & 4)
876 yi->decode_height = 576;
877 else
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;
883 } else {
884 /* If no visible size set, assume full size */
885 if (!yi->osd_vis_w)
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
892 not be legal */
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,
895 yi->decode_height);
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);
904 } else {
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)
919 int draw, display;
920 struct yuv_playback_info *yi = &itv->yuv_info;
922 if (atomic_read(&yi->next_dma_frame) == -1)
923 ivtv_yuv_init(itv);
925 draw = atomic_read(&yi->next_fill_frame);
926 display = atomic_read(&yi->next_dma_frame);
928 if (display > draw)
929 display -= IVTV_YUV_BUFFERS;
931 if (draw - display >= yi->max_frames_buffered)
932 draw = (u8)(draw - 1) % IVTV_YUV_BUFFERS;
933 else
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;
974 nf->update = 0;
975 nf->interlaced_y = 0;
976 nf->interlaced_uv = 0;
977 nf->delay = 0;
978 nf->sync_field = 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 */
987 nf->interlaced = 0;
988 if (nf->tru_h < 512 || (nf->tru_h > 576 && nf->tru_h < 1021))
989 nf->interlaced_y = 0;
990 else
991 nf->interlaced_y = 1;
993 if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
994 nf->interlaced_uv = 0;
995 else
996 nf->interlaced_uv = 1;
997 break;
999 case IVTV_YUV_MODE_AUTO:
1000 if (nf->tru_h <= lace_threshold || nf->tru_h > 576 || nf->tru_w > 720) {
1001 nf->interlaced = 0;
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;
1006 else
1007 nf->interlaced_y = 1;
1008 if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
1009 nf->interlaced_uv = 0;
1010 else
1011 nf->interlaced_uv = 1;
1012 } else {
1013 nf->interlaced = 1;
1014 nf->interlaced_y = 1;
1015 nf->interlaced_uv = 1;
1017 break;
1019 case IVTV_YUV_MODE_INTERLACED: /* Interlace mode */
1020 default:
1021 nf->interlaced = 1;
1022 nf->interlaced_y = 1;
1023 nf->interlaced_uv = 1;
1024 break;
1027 if (memcmp(&yi->old_frame_info_args, nf, sizeof(*nf))) {
1028 yi->old_frame_info_args = *nf;
1029 nf->update = 1;
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)
1047 DEFINE_WAIT(wait);
1048 int rc = 0;
1049 int got_sig = 0;
1050 /* DMA the frame */
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);
1055 return rc;
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
1061 is finished */
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))
1067 break;
1068 got_sig = 0;
1069 schedule();
1071 finish_wait(&itv->dma_waitq, &wait);
1073 /* Unmap Last DMA Xfer */
1074 ivtv_udma_unmap(itv);
1076 if (got_sig) {
1077 IVTV_DEBUG_INFO("User stopped YUV UDMA\n");
1078 mutex_unlock(&itv->udma.lock);
1079 return -EINTR;
1082 ivtv_yuv_frame_complete(itv);
1084 mutex_unlock(&itv->udma.lock);
1085 return rc;
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 */
1199 h_filter = 0;
1200 } else {
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 */
1211 v_filter_1 = 0;
1212 v_filter_2 = 1;
1213 } else {
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;
1244 /* All done. */
1245 clear_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);