Full support for Ginger Console
[linux-ginger.git] / drivers / media / video / ivtv / ivtv-yuv.c
blobc0875378acc2ffa372426c8ea05ed8497cddd7a8
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->pdev, 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 if (itv->yuv_info.track_osd) {
722 /* The OSD can be moved. Track to it */
723 f->dst_x += itv->yuv_info.osd_x_offset;
724 f->dst_y += itv->yuv_info.osd_y_offset;
727 /* Width & height for both src & dst must be even.
728 Same for coordinates. */
729 f->dst_w &= ~1;
730 f->dst_x &= ~1;
732 f->src_w += f->src_x & 1;
733 f->src_x &= ~1;
735 f->src_w &= ~1;
736 f->dst_w &= ~1;
738 f->dst_h &= ~1;
739 f->dst_y &= ~1;
741 f->src_h += f->src_y & 1;
742 f->src_y &= ~1;
744 f->src_h &= ~1;
745 f->dst_h &= ~1;
747 /* Due to rounding, we may have reduced the output size to <1/4 of
748 the source. Check again, but this time just resize. Don't change
749 source coordinates */
750 if (f->dst_w < f->src_w / 4) {
751 f->src_w &= ~3;
752 f->dst_w = f->src_w / 4;
753 f->dst_w += f->dst_w & 1;
755 if (f->dst_h < f->src_h / 4) {
756 f->src_h &= ~3;
757 f->dst_h = f->src_h / 4;
758 f->dst_h += f->dst_h & 1;
761 /* Check again. If there's nothing to safe to display, stop now */
762 if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 ||
763 (int)f->src_w <= 2 || (int)f->src_h <= 2) {
764 return IVTV_YUV_UPDATE_INVALID;
767 /* Both x offset & width are linked, so they have to be done together */
768 if ((of->dst_w != f->dst_w) || (of->src_w != f->src_w) ||
769 (of->dst_x != f->dst_x) || (of->src_x != f->src_x) ||
770 (of->pan_x != f->pan_x) || (of->vis_w != f->vis_w)) {
771 yuv_update |= IVTV_YUV_UPDATE_HORIZONTAL;
774 if ((of->src_h != f->src_h) || (of->dst_h != f->dst_h) ||
775 (of->dst_y != f->dst_y) || (of->src_y != f->src_y) ||
776 (of->pan_y != f->pan_y) || (of->vis_h != f->vis_h) ||
777 (of->lace_mode != f->lace_mode) ||
778 (of->interlaced_y != f->interlaced_y) ||
779 (of->interlaced_uv != f->interlaced_uv)) {
780 yuv_update |= IVTV_YUV_UPDATE_VERTICAL;
783 return yuv_update;
786 /* Update the scaling register to the requested value */
787 void ivtv_yuv_work_handler(struct ivtv *itv)
789 struct yuv_playback_info *yi = &itv->yuv_info;
790 struct yuv_frame_info f;
791 int frame = yi->update_frame;
792 u32 yuv_update;
794 IVTV_DEBUG_YUV("Update yuv registers for frame %d\n", frame);
795 f = yi->new_frame_info[frame];
797 if (yi->track_osd) {
798 /* Snapshot the osd pan info */
799 f.pan_x = yi->osd_x_pan;
800 f.pan_y = yi->osd_y_pan;
801 f.vis_w = yi->osd_vis_w;
802 f.vis_h = yi->osd_vis_h;
803 } else {
804 /* Not tracking the osd, so assume full screen */
805 f.pan_x = 0;
806 f.pan_y = 0;
807 f.vis_w = 720;
808 f.vis_h = yi->decode_height;
811 /* Calculate the display window coordinates. Exit if nothing left */
812 if (!(yuv_update = ivtv_yuv_window_setup(itv, &f)))
813 return;
815 if (yuv_update & IVTV_YUV_UPDATE_INVALID) {
816 write_reg(0x01008080, 0x2898);
817 } else if (yuv_update) {
818 write_reg(0x00108080, 0x2898);
820 if (yuv_update & IVTV_YUV_UPDATE_HORIZONTAL)
821 ivtv_yuv_handle_horizontal(itv, &f);
823 if (yuv_update & IVTV_YUV_UPDATE_VERTICAL)
824 ivtv_yuv_handle_vertical(itv, &f);
826 yi->old_frame_info = f;
829 static void ivtv_yuv_init(struct ivtv *itv)
831 struct yuv_playback_info *yi = &itv->yuv_info;
833 IVTV_DEBUG_YUV("ivtv_yuv_init\n");
835 /* Take a snapshot of the current register settings */
836 yi->reg_2834 = read_reg(0x02834);
837 yi->reg_2838 = read_reg(0x02838);
838 yi->reg_283c = read_reg(0x0283c);
839 yi->reg_2840 = read_reg(0x02840);
840 yi->reg_2844 = read_reg(0x02844);
841 yi->reg_2848 = read_reg(0x02848);
842 yi->reg_2854 = read_reg(0x02854);
843 yi->reg_285c = read_reg(0x0285c);
844 yi->reg_2864 = read_reg(0x02864);
845 yi->reg_2870 = read_reg(0x02870);
846 yi->reg_2874 = read_reg(0x02874);
847 yi->reg_2898 = read_reg(0x02898);
848 yi->reg_2890 = read_reg(0x02890);
850 yi->reg_289c = read_reg(0x0289c);
851 yi->reg_2918 = read_reg(0x02918);
852 yi->reg_291c = read_reg(0x0291c);
853 yi->reg_2920 = read_reg(0x02920);
854 yi->reg_2924 = read_reg(0x02924);
855 yi->reg_2928 = read_reg(0x02928);
856 yi->reg_292c = read_reg(0x0292c);
857 yi->reg_2930 = read_reg(0x02930);
858 yi->reg_2934 = read_reg(0x02934);
859 yi->reg_2938 = read_reg(0x02938);
860 yi->reg_293c = read_reg(0x0293c);
861 yi->reg_2940 = read_reg(0x02940);
862 yi->reg_2944 = read_reg(0x02944);
863 yi->reg_2948 = read_reg(0x02948);
864 yi->reg_294c = read_reg(0x0294c);
865 yi->reg_2950 = read_reg(0x02950);
866 yi->reg_2954 = read_reg(0x02954);
867 yi->reg_2958 = read_reg(0x02958);
868 yi->reg_295c = read_reg(0x0295c);
869 yi->reg_2960 = read_reg(0x02960);
870 yi->reg_2964 = read_reg(0x02964);
871 yi->reg_2968 = read_reg(0x02968);
872 yi->reg_296c = read_reg(0x0296c);
873 yi->reg_2970 = read_reg(0x02970);
875 yi->v_filter_1 = -1;
876 yi->v_filter_2 = -1;
877 yi->h_filter = -1;
879 /* Set some valid size info */
880 yi->osd_x_offset = read_reg(0x02a04) & 0x00000FFF;
881 yi->osd_y_offset = (read_reg(0x02a04) >> 16) & 0x00000FFF;
883 /* Bit 2 of reg 2878 indicates current decoder output format
884 0 : NTSC 1 : PAL */
885 if (read_reg(0x2878) & 4)
886 yi->decode_height = 576;
887 else
888 yi->decode_height = 480;
890 if (!itv->osd_info) {
891 yi->osd_vis_w = 720 - yi->osd_x_offset;
892 yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
893 } else {
894 /* If no visible size set, assume full size */
895 if (!yi->osd_vis_w)
896 yi->osd_vis_w = 720 - yi->osd_x_offset;
898 if (!yi->osd_vis_h) {
899 yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
900 } else if (yi->osd_vis_h + yi->osd_y_offset > yi->decode_height) {
901 /* If output video standard has changed, requested height may
902 not be legal */
903 IVTV_DEBUG_WARN("Clipping yuv output - fb size (%d) exceeds video standard limit (%d)\n",
904 yi->osd_vis_h + yi->osd_y_offset,
905 yi->decode_height);
906 yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
910 /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */
911 yi->blanking_ptr = kzalloc(720 * 16, GFP_KERNEL|__GFP_NOWARN);
912 if (yi->blanking_ptr) {
913 yi->blanking_dmaptr = pci_map_single(itv->pdev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE);
914 } else {
915 yi->blanking_dmaptr = 0;
916 IVTV_DEBUG_WARN("Failed to allocate yuv blanking buffer\n");
919 /* Enable YUV decoder output */
920 write_reg_sync(0x01, IVTV_REG_VDM);
922 set_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
923 atomic_set(&yi->next_dma_frame, 0);
926 /* Get next available yuv buffer on PVR350 */
927 static void ivtv_yuv_next_free(struct ivtv *itv)
929 int draw, display;
930 struct yuv_playback_info *yi = &itv->yuv_info;
932 if (atomic_read(&yi->next_dma_frame) == -1)
933 ivtv_yuv_init(itv);
935 draw = atomic_read(&yi->next_fill_frame);
936 display = atomic_read(&yi->next_dma_frame);
938 if (display > draw)
939 display -= IVTV_YUV_BUFFERS;
941 if (draw - display >= yi->max_frames_buffered)
942 draw = (u8)(draw - 1) % IVTV_YUV_BUFFERS;
943 else
944 yi->new_frame_info[draw].update = 0;
946 yi->draw_frame = draw;
949 /* Set up frame according to ivtv_dma_frame parameters */
950 static void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
952 struct yuv_playback_info *yi = &itv->yuv_info;
953 u8 frame = yi->draw_frame;
954 u8 last_frame = (u8)(frame - 1) % IVTV_YUV_BUFFERS;
955 struct yuv_frame_info *nf = &yi->new_frame_info[frame];
956 struct yuv_frame_info *of = &yi->new_frame_info[last_frame];
957 int lace_threshold = yi->lace_threshold;
959 /* Preserve old update flag in case we're overwriting a queued frame */
960 int update = nf->update;
962 /* Take a snapshot of the yuv coordinate information */
963 nf->src_x = args->src.left;
964 nf->src_y = args->src.top;
965 nf->src_w = args->src.width;
966 nf->src_h = args->src.height;
967 nf->dst_x = args->dst.left;
968 nf->dst_y = args->dst.top;
969 nf->dst_w = args->dst.width;
970 nf->dst_h = args->dst.height;
971 nf->tru_x = args->dst.left;
972 nf->tru_w = args->src_width;
973 nf->tru_h = args->src_height;
975 /* Are we going to offset the Y plane */
976 nf->offset_y = (nf->tru_h + nf->src_x < 512 - 16) ? 1 : 0;
978 nf->update = 0;
979 nf->interlaced_y = 0;
980 nf->interlaced_uv = 0;
981 nf->delay = 0;
982 nf->sync_field = 0;
983 nf->lace_mode = yi->lace_mode & IVTV_YUV_MODE_MASK;
985 if (lace_threshold < 0)
986 lace_threshold = yi->decode_height - 1;
988 /* Work out the lace settings */
989 switch (nf->lace_mode) {
990 case IVTV_YUV_MODE_PROGRESSIVE: /* Progressive mode */
991 nf->interlaced = 0;
992 if (nf->tru_h < 512 || (nf->tru_h > 576 && nf->tru_h < 1021))
993 nf->interlaced_y = 0;
994 else
995 nf->interlaced_y = 1;
997 if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
998 nf->interlaced_uv = 0;
999 else
1000 nf->interlaced_uv = 1;
1001 break;
1003 case IVTV_YUV_MODE_AUTO:
1004 if (nf->tru_h <= lace_threshold || nf->tru_h > 576 || nf->tru_w > 720) {
1005 nf->interlaced = 0;
1006 if ((nf->tru_h < 512) ||
1007 (nf->tru_h > 576 && nf->tru_h < 1021) ||
1008 (nf->tru_w > 720 && nf->tru_h < 1021))
1009 nf->interlaced_y = 0;
1010 else
1011 nf->interlaced_y = 1;
1012 if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
1013 nf->interlaced_uv = 0;
1014 else
1015 nf->interlaced_uv = 1;
1016 } else {
1017 nf->interlaced = 1;
1018 nf->interlaced_y = 1;
1019 nf->interlaced_uv = 1;
1021 break;
1023 case IVTV_YUV_MODE_INTERLACED: /* Interlace mode */
1024 default:
1025 nf->interlaced = 1;
1026 nf->interlaced_y = 1;
1027 nf->interlaced_uv = 1;
1028 break;
1031 if (memcmp(&yi->old_frame_info_args, nf, sizeof(*nf))) {
1032 yi->old_frame_info_args = *nf;
1033 nf->update = 1;
1034 IVTV_DEBUG_YUV("Requesting reg update for frame %d\n", frame);
1037 nf->update |= update;
1038 nf->sync_field = yi->lace_sync_field;
1039 nf->delay = nf->sync_field != of->sync_field;
1042 /* Frame is complete & ready for display */
1043 void ivtv_yuv_frame_complete(struct ivtv *itv)
1045 atomic_set(&itv->yuv_info.next_fill_frame,
1046 (itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS);
1049 static int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
1051 DEFINE_WAIT(wait);
1052 int rc = 0;
1053 int got_sig = 0;
1054 /* DMA the frame */
1055 mutex_lock(&itv->udma.lock);
1057 if ((rc = ivtv_yuv_prep_user_dma(itv, &itv->udma, args)) != 0) {
1058 mutex_unlock(&itv->udma.lock);
1059 return rc;
1062 ivtv_udma_prepare(itv);
1063 prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
1064 /* if no UDMA is pending and no UDMA is in progress, then the DMA
1065 is finished */
1066 while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) ||
1067 test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
1068 /* don't interrupt if the DMA is in progress but break off
1069 a still pending DMA. */
1070 got_sig = signal_pending(current);
1071 if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags))
1072 break;
1073 got_sig = 0;
1074 schedule();
1076 finish_wait(&itv->dma_waitq, &wait);
1078 /* Unmap Last DMA Xfer */
1079 ivtv_udma_unmap(itv);
1081 if (got_sig) {
1082 IVTV_DEBUG_INFO("User stopped YUV UDMA\n");
1083 mutex_unlock(&itv->udma.lock);
1084 return -EINTR;
1087 ivtv_yuv_frame_complete(itv);
1089 mutex_unlock(&itv->udma.lock);
1090 return rc;
1093 /* Setup frame according to V4L2 parameters */
1094 void ivtv_yuv_setup_stream_frame(struct ivtv *itv)
1096 struct yuv_playback_info *yi = &itv->yuv_info;
1097 struct ivtv_dma_frame dma_args;
1099 ivtv_yuv_next_free(itv);
1101 /* Copy V4L2 parameters to an ivtv_dma_frame struct... */
1102 dma_args.y_source = NULL;
1103 dma_args.uv_source = NULL;
1104 dma_args.src.left = 0;
1105 dma_args.src.top = 0;
1106 dma_args.src.width = yi->v4l2_src_w;
1107 dma_args.src.height = yi->v4l2_src_h;
1108 dma_args.dst = yi->main_rect;
1109 dma_args.src_width = yi->v4l2_src_w;
1110 dma_args.src_height = yi->v4l2_src_h;
1112 /* ... and use the same setup routine as ivtv_yuv_prep_frame */
1113 ivtv_yuv_setup_frame(itv, &dma_args);
1115 if (!itv->dma_data_req_offset)
1116 itv->dma_data_req_offset = yuv_offset[yi->draw_frame];
1119 /* Attempt to dma a frame from a user buffer */
1120 int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src)
1122 struct yuv_playback_info *yi = &itv->yuv_info;
1123 struct ivtv_dma_frame dma_args;
1125 ivtv_yuv_setup_stream_frame(itv);
1127 /* We only need to supply source addresses for this */
1128 dma_args.y_source = src;
1129 dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31);
1130 return ivtv_yuv_udma_frame(itv, &dma_args);
1133 /* IVTV_IOC_DMA_FRAME ioctl handler */
1134 int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
1136 /* IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
1138 ivtv_yuv_next_free(itv);
1139 ivtv_yuv_setup_frame(itv, args);
1140 return ivtv_yuv_udma_frame(itv, args);
1143 void ivtv_yuv_close(struct ivtv *itv)
1145 struct yuv_playback_info *yi = &itv->yuv_info;
1146 int h_filter, v_filter_1, v_filter_2;
1148 IVTV_DEBUG_YUV("ivtv_yuv_close\n");
1149 ivtv_waitq(&itv->vsync_waitq);
1151 yi->running = 0;
1152 atomic_set(&yi->next_dma_frame, -1);
1153 atomic_set(&yi->next_fill_frame, 0);
1155 /* Reset registers we have changed so mpeg playback works */
1157 /* If we fully restore this register, the display may remain active.
1158 Restore, but set one bit to blank the video. Firmware will always
1159 clear this bit when needed, so not a problem. */
1160 write_reg(yi->reg_2898 | 0x01000000, 0x2898);
1162 write_reg(yi->reg_2834, 0x02834);
1163 write_reg(yi->reg_2838, 0x02838);
1164 write_reg(yi->reg_283c, 0x0283c);
1165 write_reg(yi->reg_2840, 0x02840);
1166 write_reg(yi->reg_2844, 0x02844);
1167 write_reg(yi->reg_2848, 0x02848);
1168 write_reg(yi->reg_2854, 0x02854);
1169 write_reg(yi->reg_285c, 0x0285c);
1170 write_reg(yi->reg_2864, 0x02864);
1171 write_reg(yi->reg_2870, 0x02870);
1172 write_reg(yi->reg_2874, 0x02874);
1173 write_reg(yi->reg_2890, 0x02890);
1174 write_reg(yi->reg_289c, 0x0289c);
1176 write_reg(yi->reg_2918, 0x02918);
1177 write_reg(yi->reg_291c, 0x0291c);
1178 write_reg(yi->reg_2920, 0x02920);
1179 write_reg(yi->reg_2924, 0x02924);
1180 write_reg(yi->reg_2928, 0x02928);
1181 write_reg(yi->reg_292c, 0x0292c);
1182 write_reg(yi->reg_2930, 0x02930);
1183 write_reg(yi->reg_2934, 0x02934);
1184 write_reg(yi->reg_2938, 0x02938);
1185 write_reg(yi->reg_293c, 0x0293c);
1186 write_reg(yi->reg_2940, 0x02940);
1187 write_reg(yi->reg_2944, 0x02944);
1188 write_reg(yi->reg_2948, 0x02948);
1189 write_reg(yi->reg_294c, 0x0294c);
1190 write_reg(yi->reg_2950, 0x02950);
1191 write_reg(yi->reg_2954, 0x02954);
1192 write_reg(yi->reg_2958, 0x02958);
1193 write_reg(yi->reg_295c, 0x0295c);
1194 write_reg(yi->reg_2960, 0x02960);
1195 write_reg(yi->reg_2964, 0x02964);
1196 write_reg(yi->reg_2968, 0x02968);
1197 write_reg(yi->reg_296c, 0x0296c);
1198 write_reg(yi->reg_2970, 0x02970);
1200 /* Prepare to restore filters */
1202 /* First the horizontal filter */
1203 if ((yi->reg_2834 & 0x0000FFFF) == (yi->reg_2834 >> 16)) {
1204 /* An exact size match uses filter 0 */
1205 h_filter = 0;
1206 } else {
1207 /* Figure out which filter to use */
1208 h_filter = ((yi->reg_2834 << 16) / (yi->reg_2834 >> 16)) >> 15;
1209 h_filter = (h_filter >> 1) + (h_filter & 1);
1210 /* Only an exact size match can use filter 0. */
1211 h_filter += !h_filter;
1214 /* Now the vertical filter */
1215 if ((yi->reg_2918 & 0x0000FFFF) == (yi->reg_2918 >> 16)) {
1216 /* An exact size match uses filter 0/1 */
1217 v_filter_1 = 0;
1218 v_filter_2 = 1;
1219 } else {
1220 /* Figure out which filter to use */
1221 v_filter_1 = ((yi->reg_2918 << 16) / (yi->reg_2918 >> 16)) >> 15;
1222 v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1);
1223 /* Only an exact size match can use filter 0 */
1224 v_filter_1 += !v_filter_1;
1225 v_filter_2 = v_filter_1;
1228 /* Now restore the filters */
1229 ivtv_yuv_filter(itv, h_filter, v_filter_1, v_filter_2);
1231 /* and clear a few registers */
1232 write_reg(0, 0x02814);
1233 write_reg(0, 0x0282c);
1234 write_reg(0, 0x02904);
1235 write_reg(0, 0x02910);
1237 /* Release the blanking buffer */
1238 if (yi->blanking_ptr) {
1239 kfree(yi->blanking_ptr);
1240 yi->blanking_ptr = NULL;
1241 pci_unmap_single(itv->pdev, yi->blanking_dmaptr, 720*16, PCI_DMA_TODEVICE);
1244 /* Invalidate the old dimension information */
1245 yi->old_frame_info.src_w = 0;
1246 yi->old_frame_info.src_h = 0;
1247 yi->old_frame_info_args.src_w = 0;
1248 yi->old_frame_info_args.src_h = 0;
1250 /* All done. */
1251 clear_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);